Print this page
    
8927 sadb_x_kmc_t's KM cookie should be 64-bits (fix improper upstream)
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/inet/ip/sadb.c
          +++ new/usr/src/uts/common/inet/ip/sadb.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
  24   24   * Copyright (c) 2012 Nexenta Systems, Inc. All rights reserved.
  25   25   * Copyright (c) 2017 Joyent, Inc.
  26   26   */
  27   27  
  28   28  #include <sys/types.h>
  29   29  #include <sys/stream.h>
  30   30  #include <sys/stropts.h>
  31   31  #include <sys/strsubr.h>
  32   32  #include <sys/errno.h>
  33   33  #include <sys/ddi.h>
  34   34  #include <sys/debug.h>
  35   35  #include <sys/cmn_err.h>
  36   36  #include <sys/stream.h>
  37   37  #include <sys/strlog.h>
  38   38  #include <sys/kmem.h>
  39   39  #include <sys/sunddi.h>
  40   40  #include <sys/tihdr.h>
  41   41  #include <sys/atomic.h>
  42   42  #include <sys/socket.h>
  43   43  #include <sys/sysmacros.h>
  44   44  #include <sys/crypto/common.h>
  45   45  #include <sys/crypto/api.h>
  46   46  #include <sys/zone.h>
  47   47  #include <netinet/in.h>
  48   48  #include <net/if.h>
  49   49  #include <net/pfkeyv2.h>
  50   50  #include <net/pfpolicy.h>
  51   51  #include <inet/common.h>
  52   52  #include <netinet/ip6.h>
  53   53  #include <inet/ip.h>
  54   54  #include <inet/ip_ire.h>
  55   55  #include <inet/ip6.h>
  56   56  #include <inet/ipsec_info.h>
  57   57  #include <inet/tcp.h>
  58   58  #include <inet/sadb.h>
  59   59  #include <inet/ipsec_impl.h>
  60   60  #include <inet/ipsecah.h>
  61   61  #include <inet/ipsecesp.h>
  62   62  #include <sys/random.h>
  63   63  #include <sys/dlpi.h>
  64   64  #include <sys/strsun.h>
  65   65  #include <sys/strsubr.h>
  66   66  #include <inet/ip_if.h>
  67   67  #include <inet/ipdrop.h>
  68   68  #include <inet/ipclassifier.h>
  69   69  #include <inet/sctp_ip.h>
  70   70  #include <sys/tsol/tnet.h>
  71   71  
  72   72  /*
  73   73   * This source file contains Security Association Database (SADB) common
  74   74   * routines.  They are linked in with the AH module.  Since AH has no chance
  75   75   * of falling under export control, it was safe to link it in there.
  76   76   */
  77   77  
  78   78  static uint8_t *sadb_action_to_ecomb(uint8_t *, uint8_t *, ipsec_action_t *,
  79   79      netstack_t *);
  80   80  static ipsa_t *sadb_torch_assoc(isaf_t *, ipsa_t *);
  81   81  static void sadb_destroy_acqlist(iacqf_t **, uint_t, boolean_t,
  82   82                              netstack_t *);
  83   83  static void sadb_destroy(sadb_t *, netstack_t *);
  84   84  static mblk_t *sadb_sa2msg(ipsa_t *, sadb_msg_t *);
  85   85  static ts_label_t *sadb_label_from_sens(sadb_sens_t *, uint64_t *);
  86   86  
  87   87  static time_t sadb_add_time(time_t, uint64_t);
  88   88  static void lifetime_fuzz(ipsa_t *);
  89   89  static void age_pair_peer_list(templist_t *, sadb_t *, boolean_t);
  90   90  static int get_ipsa_pair(ipsa_query_t *, ipsap_t *, int *);
  91   91  static void init_ipsa_pair(ipsap_t *);
  92   92  static void destroy_ipsa_pair(ipsap_t *);
  93   93  static int update_pairing(ipsap_t *, ipsa_query_t *, keysock_in_t *, int *);
  94   94  static void ipsa_set_replay(ipsa_t *ipsa, uint32_t offset);
  95   95  
  96   96  /*
  97   97   * ipsacq_maxpackets is defined here to make it tunable
  98   98   * from /etc/system.
  99   99   */
 100  100  extern uint64_t ipsacq_maxpackets;
 101  101  
 102  102  #define SET_EXPIRE(sa, delta, exp) {                            \
 103  103          if (((sa)->ipsa_ ## delta) != 0) {                              \
 104  104                  (sa)->ipsa_ ## exp = sadb_add_time((sa)->ipsa_addtime,  \
 105  105                          (sa)->ipsa_ ## delta);                          \
 106  106          }                                                               \
 107  107  }
 108  108  
 109  109  #define UPDATE_EXPIRE(sa, delta, exp) {                                 \
 110  110          if (((sa)->ipsa_ ## delta) != 0) {                              \
 111  111                  time_t tmp = sadb_add_time((sa)->ipsa_usetime,          \
 112  112                          (sa)->ipsa_ ## delta);                          \
 113  113                  if (((sa)->ipsa_ ## exp) == 0)                          \
 114  114                          (sa)->ipsa_ ## exp = tmp;                       \
 115  115                  else                                                    \
 116  116                          (sa)->ipsa_ ## exp =                            \
 117  117                              MIN((sa)->ipsa_ ## exp, tmp);               \
 118  118          }                                                               \
 119  119  }
 120  120  
 121  121  
 122  122  /* wrap the macro so we can pass it as a function pointer */
 123  123  void
 124  124  sadb_sa_refrele(void *target)
 125  125  {
 126  126          IPSA_REFRELE(((ipsa_t *)target));
 127  127  }
 128  128  
 129  129  /*
 130  130   * We presume that sizeof (long) == sizeof (time_t) and that time_t is
 131  131   * a signed type.
 132  132   */
 133  133  #define TIME_MAX LONG_MAX
 134  134  
 135  135  /*
 136  136   * PF_KEY gives us lifetimes in uint64_t seconds.  We presume that
 137  137   * time_t is defined to be a signed type with the same range as
 138  138   * "long".  On ILP32 systems, we thus run the risk of wrapping around
 139  139   * at end of time, as well as "overwrapping" the clock back around
 140  140   * into a seemingly valid but incorrect future date earlier than the
 141  141   * desired expiration.
 142  142   *
 143  143   * In order to avoid odd behavior (either negative lifetimes or loss
 144  144   * of high order bits) when someone asks for bizarrely long SA
 145  145   * lifetimes, we do a saturating add for expire times.
 146  146   *
 147  147   * We presume that ILP32 systems will be past end of support life when
 148  148   * the 32-bit time_t overflows (a dangerous assumption, mind you..).
 149  149   *
 150  150   * On LP64, 2^64 seconds are about 5.8e11 years, at which point we
 151  151   * will hopefully have figured out clever ways to avoid the use of
 152  152   * fixed-sized integers in computation.
 153  153   */
 154  154  static time_t
 155  155  sadb_add_time(time_t base, uint64_t delta)
 156  156  {
 157  157          time_t sum;
 158  158  
 159  159          /*
 160  160           * Clip delta to the maximum possible time_t value to
 161  161           * prevent "overwrapping" back into a shorter-than-desired
 162  162           * future time.
 163  163           */
 164  164          if (delta > TIME_MAX)
 165  165                  delta = TIME_MAX;
 166  166          /*
 167  167           * This sum may still overflow.
 168  168           */
 169  169          sum = base + delta;
 170  170  
 171  171          /*
 172  172           * .. so if the result is less than the base, we overflowed.
 173  173           */
 174  174          if (sum < base)
 175  175                  sum = TIME_MAX;
 176  176  
 177  177          return (sum);
 178  178  }
 179  179  
 180  180  /*
 181  181   * Callers of this function have already created a working security
 182  182   * association, and have found the appropriate table & hash chain.  All this
 183  183   * function does is check duplicates, and insert the SA.  The caller needs to
 184  184   * hold the hash bucket lock and increment the refcnt before insertion.
 185  185   *
 186  186   * Return 0 if success, EEXIST if collision.
 187  187   */
 188  188  #define SA_UNIQUE_MATCH(sa1, sa2) \
 189  189          (((sa1)->ipsa_unique_id & (sa1)->ipsa_unique_mask) == \
 190  190          ((sa2)->ipsa_unique_id & (sa2)->ipsa_unique_mask))
 191  191  
 192  192  int
 193  193  sadb_insertassoc(ipsa_t *ipsa, isaf_t *bucket)
 194  194  {
 195  195          ipsa_t **ptpn = NULL;
 196  196          ipsa_t *walker;
 197  197          boolean_t unspecsrc;
 198  198  
 199  199          ASSERT(MUTEX_HELD(&bucket->isaf_lock));
 200  200  
 201  201          unspecsrc = IPSA_IS_ADDR_UNSPEC(ipsa->ipsa_srcaddr, ipsa->ipsa_addrfam);
 202  202  
 203  203          walker = bucket->isaf_ipsa;
 204  204          ASSERT(walker == NULL || ipsa->ipsa_addrfam == walker->ipsa_addrfam);
 205  205  
 206  206          /*
 207  207           * Find insertion point (pointed to with **ptpn).  Insert at the head
 208  208           * of the list unless there's an unspecified source address, then
 209  209           * insert it after the last SA with a specified source address.
 210  210           *
 211  211           * BTW, you'll have to walk the whole chain, matching on {DST, SPI}
 212  212           * checking for collisions.
 213  213           */
 214  214  
 215  215          while (walker != NULL) {
 216  216                  if (IPSA_ARE_ADDR_EQUAL(walker->ipsa_dstaddr,
 217  217                      ipsa->ipsa_dstaddr, ipsa->ipsa_addrfam)) {
 218  218                          if (walker->ipsa_spi == ipsa->ipsa_spi)
 219  219                                  return (EEXIST);
 220  220  
 221  221                          mutex_enter(&walker->ipsa_lock);
 222  222                          if (ipsa->ipsa_state == IPSA_STATE_MATURE &&
 223  223                              (walker->ipsa_flags & IPSA_F_USED) &&
 224  224                              SA_UNIQUE_MATCH(walker, ipsa)) {
 225  225                                  walker->ipsa_flags |= IPSA_F_CINVALID;
 226  226                          }
 227  227                          mutex_exit(&walker->ipsa_lock);
 228  228                  }
 229  229  
 230  230                  if (ptpn == NULL && unspecsrc) {
 231  231                          if (IPSA_IS_ADDR_UNSPEC(walker->ipsa_srcaddr,
 232  232                              walker->ipsa_addrfam))
 233  233                                  ptpn = walker->ipsa_ptpn;
 234  234                          else if (walker->ipsa_next == NULL)
 235  235                                  ptpn = &walker->ipsa_next;
 236  236                  }
 237  237  
 238  238                  walker = walker->ipsa_next;
 239  239          }
 240  240  
 241  241          if (ptpn == NULL)
 242  242                  ptpn = &bucket->isaf_ipsa;
 243  243          ipsa->ipsa_next = *ptpn;
 244  244          ipsa->ipsa_ptpn = ptpn;
 245  245          if (ipsa->ipsa_next != NULL)
 246  246                  ipsa->ipsa_next->ipsa_ptpn = &ipsa->ipsa_next;
 247  247          *ptpn = ipsa;
 248  248          ipsa->ipsa_linklock = &bucket->isaf_lock;
 249  249  
 250  250          return (0);
 251  251  }
 252  252  #undef SA_UNIQUE_MATCH
 253  253  
 254  254  /*
 255  255   * Free a security association.  Its reference count is 0, which means
 256  256   * I must free it.  The SA must be unlocked and must not be linked into
 257  257   * any fanout list.
 258  258   */
 259  259  static void
 260  260  sadb_freeassoc(ipsa_t *ipsa)
 261  261  {
 262  262          ipsec_stack_t   *ipss = ipsa->ipsa_netstack->netstack_ipsec;
 263  263          mblk_t          *asyncmp, *mp;
 264  264  
 265  265          ASSERT(ipss != NULL);
 266  266          ASSERT(MUTEX_NOT_HELD(&ipsa->ipsa_lock));
 267  267          ASSERT(ipsa->ipsa_refcnt == 0);
 268  268          ASSERT(ipsa->ipsa_next == NULL);
 269  269          ASSERT(ipsa->ipsa_ptpn == NULL);
 270  270  
 271  271  
 272  272          asyncmp = sadb_clear_lpkt(ipsa);
 273  273          if (asyncmp != NULL) {
 274  274                  mp = ip_recv_attr_free_mblk(asyncmp);
 275  275                  ip_drop_packet(mp, B_TRUE, NULL,
 276  276                      DROPPER(ipss, ipds_sadb_inlarval_timeout),
 277  277                      &ipss->ipsec_sadb_dropper);
 278  278          }
 279  279          mutex_enter(&ipsa->ipsa_lock);
 280  280  
 281  281          if (ipsa->ipsa_tsl != NULL) {
 282  282                  label_rele(ipsa->ipsa_tsl);
 283  283                  ipsa->ipsa_tsl = NULL;
 284  284          }
 285  285  
 286  286          if (ipsa->ipsa_otsl != NULL) {
 287  287                  label_rele(ipsa->ipsa_otsl);
 288  288                  ipsa->ipsa_otsl = NULL;
 289  289          }
 290  290  
 291  291          ipsec_destroy_ctx_tmpl(ipsa, IPSEC_ALG_AUTH);
 292  292          ipsec_destroy_ctx_tmpl(ipsa, IPSEC_ALG_ENCR);
 293  293          mutex_exit(&ipsa->ipsa_lock);
 294  294  
 295  295          /* bzero() these fields for paranoia's sake. */
 296  296          if (ipsa->ipsa_authkey != NULL) {
 297  297                  bzero(ipsa->ipsa_authkey, ipsa->ipsa_authkeylen);
 298  298                  kmem_free(ipsa->ipsa_authkey, ipsa->ipsa_authkeylen);
 299  299          }
 300  300          if (ipsa->ipsa_encrkey != NULL) {
 301  301                  bzero(ipsa->ipsa_encrkey, ipsa->ipsa_encrkeylen);
 302  302                  kmem_free(ipsa->ipsa_encrkey, ipsa->ipsa_encrkeylen);
 303  303          }
 304  304          if (ipsa->ipsa_nonce_buf != NULL) {
 305  305                  bzero(ipsa->ipsa_nonce_buf, sizeof (ipsec_nonce_t));
 306  306                  kmem_free(ipsa->ipsa_nonce_buf, sizeof (ipsec_nonce_t));
 307  307          }
 308  308          if (ipsa->ipsa_src_cid != NULL) {
 309  309                  IPSID_REFRELE(ipsa->ipsa_src_cid);
 310  310          }
 311  311          if (ipsa->ipsa_dst_cid != NULL) {
 312  312                  IPSID_REFRELE(ipsa->ipsa_dst_cid);
 313  313          }
 314  314          if (ipsa->ipsa_emech.cm_param != NULL)
 315  315                  kmem_free(ipsa->ipsa_emech.cm_param,
 316  316                      ipsa->ipsa_emech.cm_param_len);
 317  317  
 318  318          mutex_destroy(&ipsa->ipsa_lock);
 319  319          kmem_free(ipsa, sizeof (*ipsa));
 320  320  }
 321  321  
 322  322  /*
 323  323   * Unlink a security association from a hash bucket.  Assume the hash bucket
 324  324   * lock is held, but the association's lock is not.
 325  325   *
 326  326   * Note that we do not bump the bucket's generation number here because
 327  327   * we might not be making a visible change to the set of visible SA's.
 328  328   * All callers MUST bump the bucket's generation number before they unlock
 329  329   * the bucket if they use sadb_unlinkassoc to permanetly remove an SA which
 330  330   * was present in the bucket at the time it was locked.
 331  331   */
 332  332  void
 333  333  sadb_unlinkassoc(ipsa_t *ipsa)
 334  334  {
 335  335          ASSERT(ipsa->ipsa_linklock != NULL);
 336  336          ASSERT(MUTEX_HELD(ipsa->ipsa_linklock));
 337  337  
 338  338          /* These fields are protected by the link lock. */
 339  339          *(ipsa->ipsa_ptpn) = ipsa->ipsa_next;
 340  340          if (ipsa->ipsa_next != NULL) {
 341  341                  ipsa->ipsa_next->ipsa_ptpn = ipsa->ipsa_ptpn;
 342  342                  ipsa->ipsa_next = NULL;
 343  343          }
 344  344  
 345  345          ipsa->ipsa_ptpn = NULL;
 346  346  
 347  347          /* This may destroy the SA. */
 348  348          IPSA_REFRELE(ipsa);
 349  349  }
 350  350  
 351  351  void
 352  352  sadb_delete_cluster(ipsa_t *assoc)
 353  353  {
 354  354          uint8_t protocol;
 355  355  
 356  356          if (cl_inet_deletespi &&
 357  357              ((assoc->ipsa_state == IPSA_STATE_LARVAL) ||
 358  358              (assoc->ipsa_state == IPSA_STATE_MATURE))) {
 359  359                  protocol = (assoc->ipsa_type == SADB_SATYPE_AH) ?
 360  360                      IPPROTO_AH : IPPROTO_ESP;
 361  361                  cl_inet_deletespi(assoc->ipsa_netstack->netstack_stackid,
 362  362                      protocol, assoc->ipsa_spi, NULL);
 363  363          }
 364  364  }
 365  365  
 366  366  /*
 367  367   * Create a larval security association with the specified SPI.  All other
 368  368   * fields are zeroed.
 369  369   */
 370  370  static ipsa_t *
 371  371  sadb_makelarvalassoc(uint32_t spi, uint32_t *src, uint32_t *dst, int addrfam,
 372  372      netstack_t *ns)
 373  373  {
 374  374          ipsa_t *newbie;
 375  375  
 376  376          /*
 377  377           * Allocate...
 378  378           */
 379  379  
 380  380          newbie = (ipsa_t *)kmem_zalloc(sizeof (ipsa_t), KM_NOSLEEP);
 381  381          if (newbie == NULL) {
 382  382                  /* Can't make new larval SA. */
 383  383                  return (NULL);
 384  384          }
 385  385  
 386  386          /* Assigned requested SPI, assume caller does SPI allocation magic. */
 387  387          newbie->ipsa_spi = spi;
 388  388          newbie->ipsa_netstack = ns;     /* No netstack_hold */
 389  389  
 390  390          /*
 391  391           * Copy addresses...
 392  392           */
 393  393  
 394  394          IPSA_COPY_ADDR(newbie->ipsa_srcaddr, src, addrfam);
 395  395          IPSA_COPY_ADDR(newbie->ipsa_dstaddr, dst, addrfam);
 396  396  
 397  397          newbie->ipsa_addrfam = addrfam;
 398  398  
 399  399          /*
 400  400           * Set common initialization values, including refcnt.
 401  401           */
 402  402          mutex_init(&newbie->ipsa_lock, NULL, MUTEX_DEFAULT, NULL);
 403  403          newbie->ipsa_state = IPSA_STATE_LARVAL;
 404  404          newbie->ipsa_refcnt = 1;
 405  405          newbie->ipsa_freefunc = sadb_freeassoc;
 406  406  
 407  407          /*
 408  408           * There aren't a lot of other common initialization values, as
 409  409           * they are copied in from the PF_KEY message.
 410  410           */
 411  411  
 412  412          return (newbie);
 413  413  }
 414  414  
 415  415  /*
 416  416   * Call me to initialize a security association fanout.
 417  417   */
 418  418  static int
 419  419  sadb_init_fanout(isaf_t **tablep, uint_t size, int kmflag)
 420  420  {
 421  421          isaf_t *table;
 422  422          int i;
 423  423  
 424  424          table = (isaf_t *)kmem_alloc(size * sizeof (*table), kmflag);
 425  425          *tablep = table;
 426  426  
 427  427          if (table == NULL)
 428  428                  return (ENOMEM);
 429  429  
 430  430          for (i = 0; i < size; i++) {
 431  431                  mutex_init(&(table[i].isaf_lock), NULL, MUTEX_DEFAULT, NULL);
 432  432                  table[i].isaf_ipsa = NULL;
 433  433                  table[i].isaf_gen = 0;
 434  434          }
 435  435  
 436  436          return (0);
 437  437  }
 438  438  
 439  439  /*
 440  440   * Call me to initialize an acquire fanout
 441  441   */
 442  442  static int
 443  443  sadb_init_acfanout(iacqf_t **tablep, uint_t size, int kmflag)
 444  444  {
 445  445          iacqf_t *table;
 446  446          int i;
 447  447  
 448  448          table = (iacqf_t *)kmem_alloc(size * sizeof (*table), kmflag);
 449  449          *tablep = table;
 450  450  
 451  451          if (table == NULL)
 452  452                  return (ENOMEM);
 453  453  
 454  454          for (i = 0; i < size; i++) {
 455  455                  mutex_init(&(table[i].iacqf_lock), NULL, MUTEX_DEFAULT, NULL);
 456  456                  table[i].iacqf_ipsacq = NULL;
 457  457          }
 458  458  
 459  459          return (0);
 460  460  }
 461  461  
 462  462  /*
 463  463   * Attempt to initialize an SADB instance.  On failure, return ENOMEM;
 464  464   * caller must clean up partial allocations.
 465  465   */
 466  466  static int
 467  467  sadb_init_trial(sadb_t *sp, uint_t size, int kmflag)
 468  468  {
 469  469          ASSERT(sp->sdb_of == NULL);
 470  470          ASSERT(sp->sdb_if == NULL);
 471  471          ASSERT(sp->sdb_acq == NULL);
 472  472  
 473  473          sp->sdb_hashsize = size;
 474  474          if (sadb_init_fanout(&sp->sdb_of, size, kmflag) != 0)
 475  475                  return (ENOMEM);
 476  476          if (sadb_init_fanout(&sp->sdb_if, size, kmflag) != 0)
 477  477                  return (ENOMEM);
 478  478          if (sadb_init_acfanout(&sp->sdb_acq, size, kmflag) != 0)
 479  479                  return (ENOMEM);
 480  480  
 481  481          return (0);
 482  482  }
 483  483  
 484  484  /*
 485  485   * Call me to initialize an SADB instance; fall back to default size on failure.
 486  486   */
 487  487  static void
 488  488  sadb_init(const char *name, sadb_t *sp, uint_t size, uint_t ver,
 489  489      netstack_t *ns)
 490  490  {
 491  491          ASSERT(sp->sdb_of == NULL);
 492  492          ASSERT(sp->sdb_if == NULL);
 493  493          ASSERT(sp->sdb_acq == NULL);
 494  494  
 495  495          if (size < IPSEC_DEFAULT_HASH_SIZE)
 496  496                  size = IPSEC_DEFAULT_HASH_SIZE;
 497  497  
 498  498          if (sadb_init_trial(sp, size, KM_NOSLEEP) != 0) {
 499  499  
 500  500                  cmn_err(CE_WARN,
 501  501                      "Unable to allocate %u entry IPv%u %s SADB hash table",
 502  502                      size, ver, name);
 503  503  
 504  504                  sadb_destroy(sp, ns);
 505  505                  size = IPSEC_DEFAULT_HASH_SIZE;
 506  506                  cmn_err(CE_WARN, "Falling back to %d entries", size);
 507  507                  (void) sadb_init_trial(sp, size, KM_SLEEP);
 508  508          }
 509  509  }
 510  510  
 511  511  
 512  512  /*
 513  513   * Initialize an SADB-pair.
 514  514   */
 515  515  void
 516  516  sadbp_init(const char *name, sadbp_t *sp, int type, int size, netstack_t *ns)
 517  517  {
 518  518          sadb_init(name, &sp->s_v4, size, 4, ns);
 519  519          sadb_init(name, &sp->s_v6, size, 6, ns);
 520  520  
 521  521          sp->s_satype = type;
 522  522  
 523  523          ASSERT((type == SADB_SATYPE_AH) || (type == SADB_SATYPE_ESP));
 524  524          if (type == SADB_SATYPE_AH) {
 525  525                  ipsec_stack_t   *ipss = ns->netstack_ipsec;
 526  526  
 527  527                  ip_drop_register(&ipss->ipsec_sadb_dropper, "IPsec SADB");
 528  528                  sp->s_addflags = AH_ADD_SETTABLE_FLAGS;
 529  529                  sp->s_updateflags = AH_UPDATE_SETTABLE_FLAGS;
 530  530          } else {
 531  531                  sp->s_addflags = ESP_ADD_SETTABLE_FLAGS;
 532  532                  sp->s_updateflags = ESP_UPDATE_SETTABLE_FLAGS;
 533  533          }
 534  534  }
 535  535  
 536  536  /*
 537  537   * Deliver a single SADB_DUMP message representing a single SA.  This is
 538  538   * called many times by sadb_dump().
 539  539   *
 540  540   * If the return value of this is ENOBUFS (not the same as ENOMEM), then
 541  541   * the caller should take that as a hint that dupb() on the "original answer"
 542  542   * failed, and that perhaps the caller should try again with a copyb()ed
 543  543   * "original answer".
 544  544   */
 545  545  static int
 546  546  sadb_dump_deliver(queue_t *pfkey_q, mblk_t *original_answer, ipsa_t *ipsa,
 547  547      sadb_msg_t *samsg)
 548  548  {
 549  549          mblk_t *answer;
 550  550  
 551  551          answer = dupb(original_answer);
 552  552          if (answer == NULL)
 553  553                  return (ENOBUFS);
 554  554          answer->b_cont = sadb_sa2msg(ipsa, samsg);
 555  555          if (answer->b_cont == NULL) {
 556  556                  freeb(answer);
 557  557                  return (ENOMEM);
 558  558          }
 559  559  
 560  560          /* Just do a putnext, and let keysock deal with flow control. */
 561  561          putnext(pfkey_q, answer);
 562  562          return (0);
 563  563  }
 564  564  
 565  565  /*
 566  566   * Common function to allocate and prepare a keysock_out_t M_CTL message.
 567  567   */
 568  568  mblk_t *
 569  569  sadb_keysock_out(minor_t serial)
 570  570  {
 571  571          mblk_t *mp;
 572  572          keysock_out_t *kso;
 573  573  
 574  574          mp = allocb(sizeof (ipsec_info_t), BPRI_HI);
 575  575          if (mp != NULL) {
 576  576                  mp->b_datap->db_type = M_CTL;
 577  577                  mp->b_wptr += sizeof (ipsec_info_t);
 578  578                  kso = (keysock_out_t *)mp->b_rptr;
 579  579                  kso->ks_out_type = KEYSOCK_OUT;
 580  580                  kso->ks_out_len = sizeof (*kso);
 581  581                  kso->ks_out_serial = serial;
 582  582          }
 583  583  
 584  584          return (mp);
 585  585  }
 586  586  
 587  587  /*
 588  588   * Perform an SADB_DUMP, spewing out every SA in an array of SA fanouts
 589  589   * to keysock.
 590  590   */
 591  591  static int
 592  592  sadb_dump_fanout(queue_t *pfkey_q, mblk_t *mp, minor_t serial, isaf_t *fanout,
 593  593      int num_entries, boolean_t do_peers, time_t active_time)
 594  594  {
 595  595          int i, error = 0;
 596  596          mblk_t *original_answer;
 597  597          ipsa_t *walker;
 598  598          sadb_msg_t *samsg;
 599  599          time_t  current;
 600  600  
 601  601          /*
 602  602           * For each IPSA hash bucket do:
 603  603           *      - Hold the mutex
 604  604           *      - Walk each entry, doing an sadb_dump_deliver() on it.
 605  605           */
 606  606          ASSERT(mp->b_cont != NULL);
 607  607          samsg = (sadb_msg_t *)mp->b_cont->b_rptr;
 608  608  
 609  609          original_answer = sadb_keysock_out(serial);
 610  610          if (original_answer == NULL)
 611  611                  return (ENOMEM);
 612  612  
 613  613          current = gethrestime_sec();
 614  614          for (i = 0; i < num_entries; i++) {
 615  615                  mutex_enter(&fanout[i].isaf_lock);
 616  616                  for (walker = fanout[i].isaf_ipsa; walker != NULL;
 617  617                      walker = walker->ipsa_next) {
 618  618                          if (!do_peers && walker->ipsa_haspeer)
 619  619                                  continue;
 620  620                          if ((active_time != 0) &&
 621  621                              ((current - walker->ipsa_lastuse) > active_time))
 622  622                                  continue;
 623  623                          error = sadb_dump_deliver(pfkey_q, original_answer,
 624  624                              walker, samsg);
 625  625                          if (error == ENOBUFS) {
 626  626                                  mblk_t *new_original_answer;
 627  627  
 628  628                                  /* Ran out of dupb's.  Try a copyb. */
 629  629                                  new_original_answer = copyb(original_answer);
 630  630                                  if (new_original_answer == NULL) {
 631  631                                          error = ENOMEM;
 632  632                                  } else {
 633  633                                          freeb(original_answer);
 634  634                                          original_answer = new_original_answer;
 635  635                                          error = sadb_dump_deliver(pfkey_q,
 636  636                                              original_answer, walker, samsg);
 637  637                                  }
 638  638                          }
 639  639                          if (error != 0)
 640  640                                  break;  /* out of for loop. */
 641  641                  }
 642  642                  mutex_exit(&fanout[i].isaf_lock);
 643  643                  if (error != 0)
 644  644                          break;  /* out of for loop. */
 645  645          }
 646  646  
 647  647          freeb(original_answer);
 648  648          return (error);
 649  649  }
 650  650  
 651  651  /*
 652  652   * Dump an entire SADB; outbound first, then inbound.
 653  653   */
 654  654  
 655  655  int
 656  656  sadb_dump(queue_t *pfkey_q, mblk_t *mp, keysock_in_t *ksi, sadb_t *sp)
 657  657  {
 658  658          int error;
 659  659          time_t  active_time = 0;
 660  660          sadb_x_edump_t  *edump =
 661  661              (sadb_x_edump_t *)ksi->ks_in_extv[SADB_X_EXT_EDUMP];
 662  662  
 663  663          if (edump != NULL) {
 664  664                  active_time = edump->sadb_x_edump_timeout;
 665  665          }
 666  666  
 667  667          /* Dump outbound */
 668  668          error = sadb_dump_fanout(pfkey_q, mp, ksi->ks_in_serial, sp->sdb_of,
 669  669              sp->sdb_hashsize, B_TRUE, active_time);
 670  670          if (error)
 671  671                  return (error);
 672  672  
 673  673          /* Dump inbound */
 674  674          return sadb_dump_fanout(pfkey_q, mp, ksi->ks_in_serial, sp->sdb_if,
 675  675              sp->sdb_hashsize, B_FALSE, active_time);
 676  676  }
 677  677  
 678  678  /*
 679  679   * Generic sadb table walker.
 680  680   *
 681  681   * Call "walkfn" for each SA in each bucket in "table"; pass the
 682  682   * bucket, the entry and "cookie" to the callback function.
 683  683   * Take care to ensure that walkfn can delete the SA without screwing
 684  684   * up our traverse.
 685  685   *
 686  686   * The bucket is locked for the duration of the callback, both so that the
 687  687   * callback can just call sadb_unlinkassoc() when it wants to delete something,
 688  688   * and so that no new entries are added while we're walking the list.
 689  689   */
 690  690  static void
 691  691  sadb_walker(isaf_t *table, uint_t numentries,
 692  692      void (*walkfn)(isaf_t *head, ipsa_t *entry, void *cookie),
 693  693      void *cookie)
 694  694  {
 695  695          int i;
 696  696          for (i = 0; i < numentries; i++) {
 697  697                  ipsa_t *entry, *next;
 698  698  
 699  699                  mutex_enter(&table[i].isaf_lock);
 700  700  
 701  701                  for (entry = table[i].isaf_ipsa; entry != NULL;
 702  702                      entry = next) {
 703  703                          next = entry->ipsa_next;
 704  704                          (*walkfn)(&table[i], entry, cookie);
 705  705                  }
 706  706                  mutex_exit(&table[i].isaf_lock);
 707  707          }
 708  708  }
 709  709  
 710  710  /*
 711  711   * Call me to free up a security association fanout.  Use the forever
 712  712   * variable to indicate freeing up the SAs (forever == B_FALSE, e.g.
 713  713   * an SADB_FLUSH message), or destroying everything (forever == B_TRUE,
 714  714   * when a module is unloaded).
 715  715   */
 716  716  static void
 717  717  sadb_destroyer(isaf_t **tablep, uint_t numentries, boolean_t forever,
 718  718      boolean_t inbound)
 719  719  {
 720  720          int i;
 721  721          isaf_t *table = *tablep;
 722  722          uint8_t protocol;
 723  723          ipsa_t *sa;
 724  724          netstackid_t sid;
 725  725  
 726  726          if (table == NULL)
 727  727                  return;
 728  728  
 729  729          for (i = 0; i < numentries; i++) {
 730  730                  mutex_enter(&table[i].isaf_lock);
 731  731                  while ((sa = table[i].isaf_ipsa) != NULL) {
 732  732                          if (inbound && cl_inet_deletespi &&
 733  733                              (sa->ipsa_state != IPSA_STATE_ACTIVE_ELSEWHERE) &&
 734  734                              (sa->ipsa_state != IPSA_STATE_IDLE)) {
 735  735                                  protocol = (sa->ipsa_type == SADB_SATYPE_AH) ?
 736  736                                      IPPROTO_AH : IPPROTO_ESP;
 737  737                                  sid = sa->ipsa_netstack->netstack_stackid;
 738  738                                  cl_inet_deletespi(sid, protocol, sa->ipsa_spi,
 739  739                                      NULL);
 740  740                          }
 741  741                          sadb_unlinkassoc(sa);
 742  742                  }
 743  743                  table[i].isaf_gen++;
 744  744                  mutex_exit(&table[i].isaf_lock);
 745  745                  if (forever)
 746  746                          mutex_destroy(&(table[i].isaf_lock));
 747  747          }
 748  748  
 749  749          if (forever) {
 750  750                  *tablep = NULL;
 751  751                  kmem_free(table, numentries * sizeof (*table));
 752  752          }
 753  753  }
 754  754  
 755  755  /*
 756  756   * Entry points to sadb_destroyer().
 757  757   */
 758  758  static void
 759  759  sadb_flush(sadb_t *sp, netstack_t *ns)
 760  760  {
 761  761          /*
 762  762           * Flush out each bucket, one at a time.  Were it not for keysock's
 763  763           * enforcement, there would be a subtlety where I could add on the
 764  764           * heels of a flush.  With keysock's enforcement, however, this
 765  765           * makes ESP's job easy.
 766  766           */
 767  767          sadb_destroyer(&sp->sdb_of, sp->sdb_hashsize, B_FALSE, B_FALSE);
 768  768          sadb_destroyer(&sp->sdb_if, sp->sdb_hashsize, B_FALSE, B_TRUE);
 769  769  
 770  770          /* For each acquire, destroy it; leave the bucket mutex alone. */
 771  771          sadb_destroy_acqlist(&sp->sdb_acq, sp->sdb_hashsize, B_FALSE, ns);
 772  772  }
 773  773  
 774  774  static void
 775  775  sadb_destroy(sadb_t *sp, netstack_t *ns)
 776  776  {
 777  777          sadb_destroyer(&sp->sdb_of, sp->sdb_hashsize, B_TRUE, B_FALSE);
 778  778          sadb_destroyer(&sp->sdb_if, sp->sdb_hashsize, B_TRUE, B_TRUE);
 779  779  
 780  780          /* For each acquire, destroy it, including the bucket mutex. */
 781  781          sadb_destroy_acqlist(&sp->sdb_acq, sp->sdb_hashsize, B_TRUE, ns);
 782  782  
 783  783          ASSERT(sp->sdb_of == NULL);
 784  784          ASSERT(sp->sdb_if == NULL);
 785  785          ASSERT(sp->sdb_acq == NULL);
 786  786  }
 787  787  
 788  788  void
 789  789  sadbp_flush(sadbp_t *spp, netstack_t *ns)
 790  790  {
 791  791          sadb_flush(&spp->s_v4, ns);
 792  792          sadb_flush(&spp->s_v6, ns);
 793  793  }
 794  794  
 795  795  void
 796  796  sadbp_destroy(sadbp_t *spp, netstack_t *ns)
 797  797  {
 798  798          sadb_destroy(&spp->s_v4, ns);
 799  799          sadb_destroy(&spp->s_v6, ns);
 800  800  
 801  801          if (spp->s_satype == SADB_SATYPE_AH) {
 802  802                  ipsec_stack_t   *ipss = ns->netstack_ipsec;
 803  803  
 804  804                  ip_drop_unregister(&ipss->ipsec_sadb_dropper);
 805  805          }
 806  806  }
 807  807  
 808  808  
 809  809  /*
 810  810   * Check hard vs. soft lifetimes.  If there's a reality mismatch (e.g.
 811  811   * soft lifetimes > hard lifetimes) return an appropriate diagnostic for
 812  812   * EINVAL.
 813  813   */
 814  814  int
 815  815  sadb_hardsoftchk(sadb_lifetime_t *hard, sadb_lifetime_t *soft,
 816  816      sadb_lifetime_t *idle)
 817  817  {
 818  818          if (hard == NULL || soft == NULL)
 819  819                  return (0);
 820  820  
 821  821          if (hard->sadb_lifetime_allocations != 0 &&
 822  822              soft->sadb_lifetime_allocations != 0 &&
 823  823              hard->sadb_lifetime_allocations < soft->sadb_lifetime_allocations)
 824  824                  return (SADB_X_DIAGNOSTIC_ALLOC_HSERR);
 825  825  
 826  826          if (hard->sadb_lifetime_bytes != 0 &&
 827  827              soft->sadb_lifetime_bytes != 0 &&
 828  828              hard->sadb_lifetime_bytes < soft->sadb_lifetime_bytes)
 829  829                  return (SADB_X_DIAGNOSTIC_BYTES_HSERR);
 830  830  
 831  831          if (hard->sadb_lifetime_addtime != 0 &&
 832  832              soft->sadb_lifetime_addtime != 0 &&
 833  833              hard->sadb_lifetime_addtime < soft->sadb_lifetime_addtime)
 834  834                  return (SADB_X_DIAGNOSTIC_ADDTIME_HSERR);
 835  835  
 836  836          if (hard->sadb_lifetime_usetime != 0 &&
 837  837              soft->sadb_lifetime_usetime != 0 &&
 838  838              hard->sadb_lifetime_usetime < soft->sadb_lifetime_usetime)
 839  839                  return (SADB_X_DIAGNOSTIC_USETIME_HSERR);
 840  840  
 841  841          if (idle != NULL) {
 842  842                  if (hard->sadb_lifetime_addtime != 0 &&
 843  843                      idle->sadb_lifetime_addtime != 0 &&
 844  844                      hard->sadb_lifetime_addtime < idle->sadb_lifetime_addtime)
 845  845                          return (SADB_X_DIAGNOSTIC_ADDTIME_HSERR);
 846  846  
 847  847                  if (soft->sadb_lifetime_addtime != 0 &&
 848  848                      idle->sadb_lifetime_addtime != 0 &&
 849  849                      soft->sadb_lifetime_addtime < idle->sadb_lifetime_addtime)
 850  850                          return (SADB_X_DIAGNOSTIC_ADDTIME_HSERR);
 851  851  
 852  852                  if (hard->sadb_lifetime_usetime != 0 &&
 853  853                      idle->sadb_lifetime_usetime != 0 &&
 854  854                      hard->sadb_lifetime_usetime < idle->sadb_lifetime_usetime)
 855  855                          return (SADB_X_DIAGNOSTIC_USETIME_HSERR);
 856  856  
 857  857                  if (soft->sadb_lifetime_usetime != 0 &&
 858  858                      idle->sadb_lifetime_usetime != 0 &&
 859  859                      soft->sadb_lifetime_usetime < idle->sadb_lifetime_usetime)
 860  860                          return (SADB_X_DIAGNOSTIC_USETIME_HSERR);
 861  861          }
 862  862  
 863  863          return (0);
 864  864  }
 865  865  
 866  866  /*
 867  867   * Sanity check sensitivity labels.
 868  868   *
 869  869   * For now, just reject labels on unlabeled systems.
 870  870   */
 871  871  int
 872  872  sadb_labelchk(keysock_in_t *ksi)
 873  873  {
 874  874          if (!is_system_labeled()) {
 875  875                  if (ksi->ks_in_extv[SADB_EXT_SENSITIVITY] != NULL)
 876  876                          return (SADB_X_DIAGNOSTIC_BAD_LABEL);
 877  877  
 878  878                  if (ksi->ks_in_extv[SADB_X_EXT_OUTER_SENS] != NULL)
 879  879                          return (SADB_X_DIAGNOSTIC_BAD_LABEL);
 880  880          }
 881  881  
 882  882          return (0);
 883  883  }
 884  884  
 885  885  /*
 886  886   * Clone a security association for the purposes of inserting a single SA
 887  887   * into inbound and outbound tables respectively. This function should only
 888  888   * be called from sadb_common_add().
 889  889   */
 890  890  static ipsa_t *
 891  891  sadb_cloneassoc(ipsa_t *ipsa)
 892  892  {
 893  893          ipsa_t *newbie;
 894  894          boolean_t error = B_FALSE;
 895  895  
 896  896          ASSERT(MUTEX_NOT_HELD(&(ipsa->ipsa_lock)));
 897  897  
 898  898          newbie = kmem_alloc(sizeof (ipsa_t), KM_NOSLEEP);
 899  899          if (newbie == NULL)
 900  900                  return (NULL);
 901  901  
 902  902          /* Copy over what we can. */
 903  903          *newbie = *ipsa;
 904  904  
 905  905          /* bzero and initialize locks, in case *_init() allocates... */
 906  906          mutex_init(&newbie->ipsa_lock, NULL, MUTEX_DEFAULT, NULL);
 907  907  
 908  908          if (newbie->ipsa_tsl != NULL)
 909  909                  label_hold(newbie->ipsa_tsl);
 910  910  
 911  911          if (newbie->ipsa_otsl != NULL)
 912  912                  label_hold(newbie->ipsa_otsl);
 913  913  
 914  914          /*
 915  915           * While somewhat dain-bramaged, the most graceful way to
 916  916           * recover from errors is to keep plowing through the
 917  917           * allocations, and getting what I can.  It's easier to call
 918  918           * sadb_freeassoc() on the stillborn clone when all the
 919  919           * pointers aren't pointing to the parent's data.
 920  920           */
 921  921  
 922  922          if (ipsa->ipsa_authkey != NULL) {
 923  923                  newbie->ipsa_authkey = kmem_alloc(newbie->ipsa_authkeylen,
 924  924                      KM_NOSLEEP);
 925  925                  if (newbie->ipsa_authkey == NULL) {
 926  926                          error = B_TRUE;
 927  927                  } else {
 928  928                          bcopy(ipsa->ipsa_authkey, newbie->ipsa_authkey,
 929  929                              newbie->ipsa_authkeylen);
 930  930  
 931  931                          newbie->ipsa_kcfauthkey.ck_data =
 932  932                              newbie->ipsa_authkey;
 933  933                  }
 934  934  
 935  935                  if (newbie->ipsa_amech.cm_param != NULL) {
 936  936                          newbie->ipsa_amech.cm_param =
 937  937                              (char *)&newbie->ipsa_mac_len;
 938  938                  }
 939  939          }
 940  940  
 941  941          if (ipsa->ipsa_encrkey != NULL) {
 942  942                  newbie->ipsa_encrkey = kmem_alloc(newbie->ipsa_encrkeylen,
 943  943                      KM_NOSLEEP);
 944  944                  if (newbie->ipsa_encrkey == NULL) {
 945  945                          error = B_TRUE;
 946  946                  } else {
 947  947                          bcopy(ipsa->ipsa_encrkey, newbie->ipsa_encrkey,
 948  948                              newbie->ipsa_encrkeylen);
 949  949  
 950  950                          newbie->ipsa_kcfencrkey.ck_data =
 951  951                              newbie->ipsa_encrkey;
 952  952                  }
 953  953          }
 954  954  
 955  955          newbie->ipsa_authtmpl = NULL;
 956  956          newbie->ipsa_encrtmpl = NULL;
 957  957          newbie->ipsa_haspeer = B_TRUE;
 958  958  
 959  959          if (ipsa->ipsa_src_cid != NULL) {
 960  960                  newbie->ipsa_src_cid = ipsa->ipsa_src_cid;
 961  961                  IPSID_REFHOLD(ipsa->ipsa_src_cid);
 962  962          }
 963  963  
 964  964          if (ipsa->ipsa_dst_cid != NULL) {
 965  965                  newbie->ipsa_dst_cid = ipsa->ipsa_dst_cid;
 966  966                  IPSID_REFHOLD(ipsa->ipsa_dst_cid);
 967  967          }
 968  968  
 969  969          if (error) {
 970  970                  sadb_freeassoc(newbie);
 971  971                  return (NULL);
 972  972          }
 973  973  
 974  974          return (newbie);
 975  975  }
 976  976  
 977  977  /*
 978  978   * Initialize a SADB address extension at the address specified by addrext.
 979  979   * Return a pointer to the end of the new address extension.
 980  980   */
 981  981  static uint8_t *
 982  982  sadb_make_addr_ext(uint8_t *start, uint8_t *end, uint16_t exttype,
 983  983      sa_family_t af, uint32_t *addr, uint16_t port, uint8_t proto, int prefix)
 984  984  {
 985  985          struct sockaddr_in *sin;
 986  986          struct sockaddr_in6 *sin6;
 987  987          uint8_t *cur = start;
 988  988          int addrext_len;
 989  989          int sin_len;
 990  990          sadb_address_t *addrext = (sadb_address_t *)cur;
 991  991  
 992  992          if (cur == NULL)
 993  993                  return (NULL);
 994  994  
 995  995          cur += sizeof (*addrext);
 996  996          if (cur > end)
 997  997                  return (NULL);
 998  998  
 999  999          addrext->sadb_address_proto = proto;
1000 1000          addrext->sadb_address_prefixlen = prefix;
1001 1001          addrext->sadb_address_reserved = 0;
1002 1002          addrext->sadb_address_exttype = exttype;
1003 1003  
1004 1004          switch (af) {
1005 1005          case AF_INET:
1006 1006                  sin = (struct sockaddr_in *)cur;
1007 1007                  sin_len = sizeof (*sin);
1008 1008                  cur += sin_len;
1009 1009                  if (cur > end)
1010 1010                          return (NULL);
1011 1011  
1012 1012                  sin->sin_family = af;
1013 1013                  bzero(sin->sin_zero, sizeof (sin->sin_zero));
1014 1014                  sin->sin_port = port;
1015 1015                  IPSA_COPY_ADDR(&sin->sin_addr, addr, af);
1016 1016                  break;
1017 1017          case AF_INET6:
1018 1018                  sin6 = (struct sockaddr_in6 *)cur;
1019 1019                  sin_len = sizeof (*sin6);
1020 1020                  cur += sin_len;
1021 1021                  if (cur > end)
1022 1022                          return (NULL);
1023 1023  
1024 1024                  bzero(sin6, sizeof (*sin6));
1025 1025                  sin6->sin6_family = af;
1026 1026                  sin6->sin6_port = port;
1027 1027                  IPSA_COPY_ADDR(&sin6->sin6_addr, addr, af);
1028 1028                  break;
1029 1029          }
1030 1030  
1031 1031          addrext_len = roundup(cur - start, sizeof (uint64_t));
1032 1032          addrext->sadb_address_len = SADB_8TO64(addrext_len);
1033 1033  
1034 1034          cur = start + addrext_len;
1035 1035          if (cur > end)
1036 1036                  cur = NULL;
1037 1037  
1038 1038          return (cur);
1039 1039  }
1040 1040  
1041 1041  /*
1042 1042   * Construct a key management cookie extension.
1043 1043   */
1044 1044  
1045 1045  static uint8_t *
1046 1046  sadb_make_kmc_ext(uint8_t *cur, uint8_t *end, uint32_t kmp, uint64_t kmc)
1047 1047  {
1048 1048          sadb_x_kmc_t *kmcext = (sadb_x_kmc_t *)cur;
1049 1049  
1050 1050          if (cur == NULL)
1051 1051                  return (NULL);
1052 1052  
1053 1053          cur += sizeof (*kmcext);
1054 1054  
1055 1055          if (cur > end)
1056 1056                  return (NULL);
1057 1057  
1058 1058          kmcext->sadb_x_kmc_len = SADB_8TO64(sizeof (*kmcext));
1059 1059          kmcext->sadb_x_kmc_exttype = SADB_X_EXT_KM_COOKIE;
1060 1060          kmcext->sadb_x_kmc_proto = kmp;
1061 1061          kmcext->sadb_x_kmc_cookie64 = kmc;
1062 1062  
1063 1063          return (cur);
1064 1064  }
1065 1065  
1066 1066  /*
1067 1067   * Given an original message header with sufficient space following it, and an
1068 1068   * SA, construct a full PF_KEY message with all of the relevant extensions.
1069 1069   * This is mostly used for SADB_GET, and SADB_DUMP.
1070 1070   */
1071 1071  static mblk_t *
1072 1072  sadb_sa2msg(ipsa_t *ipsa, sadb_msg_t *samsg)
1073 1073  {
1074 1074          int alloclen, addrsize, paddrsize, authsize, encrsize;
1075 1075          int srcidsize, dstidsize, senslen, osenslen;
1076 1076          sa_family_t fam, pfam;  /* Address family for SADB_EXT_ADDRESS */
1077 1077                                  /* src/dst and proxy sockaddrs. */
1078 1078          /*
1079 1079           * The following are pointers into the PF_KEY message this PF_KEY
1080 1080           * message creates.
1081 1081           */
1082 1082          sadb_msg_t *newsamsg;
1083 1083          sadb_sa_t *assoc;
1084 1084          sadb_lifetime_t *lt;
1085 1085          sadb_key_t *key;
1086 1086          sadb_ident_t *ident;
1087 1087          sadb_sens_t *sens;
1088 1088          sadb_ext_t *walker;     /* For when we need a generic ext. pointer. */
1089 1089          sadb_x_replay_ctr_t *repl_ctr;
1090 1090          sadb_x_pair_t *pair_ext;
1091 1091  
1092 1092          mblk_t *mp;
1093 1093          uint8_t *cur, *end;
1094 1094          /* These indicate the presence of the above extension fields. */
1095 1095          boolean_t soft = B_FALSE, hard = B_FALSE;
1096 1096          boolean_t isrc = B_FALSE, idst = B_FALSE;
1097 1097          boolean_t auth = B_FALSE, encr = B_FALSE;
1098 1098          boolean_t sensinteg = B_FALSE, osensinteg = B_FALSE;
1099 1099          boolean_t srcid = B_FALSE, dstid = B_FALSE;
1100 1100          boolean_t idle;
1101 1101          boolean_t paired;
1102 1102          uint32_t otherspi;
1103 1103  
1104 1104          /* First off, figure out the allocation length for this message. */
1105 1105          /*
1106 1106           * Constant stuff.  This includes base, SA, address (src, dst),
1107 1107           * and lifetime (current).
1108 1108           */
1109 1109          alloclen = sizeof (sadb_msg_t) + sizeof (sadb_sa_t) +
1110 1110              sizeof (sadb_lifetime_t);
1111 1111  
1112 1112          fam = ipsa->ipsa_addrfam;
1113 1113          switch (fam) {
1114 1114          case AF_INET:
1115 1115                  addrsize = roundup(sizeof (struct sockaddr_in) +
1116 1116                      sizeof (sadb_address_t), sizeof (uint64_t));
1117 1117                  break;
1118 1118          case AF_INET6:
1119 1119                  addrsize = roundup(sizeof (struct sockaddr_in6) +
1120 1120                      sizeof (sadb_address_t), sizeof (uint64_t));
1121 1121                  break;
1122 1122          default:
1123 1123                  return (NULL);
1124 1124          }
1125 1125          /*
1126 1126           * Allocate TWO address extensions, for source and destination.
1127 1127           * (Thus, the * 2.)
1128 1128           */
1129 1129          alloclen += addrsize * 2;
1130 1130          if (ipsa->ipsa_flags & IPSA_F_NATT_REM)
1131 1131                  alloclen += addrsize;
1132 1132          if (ipsa->ipsa_flags & IPSA_F_NATT_LOC)
1133 1133                  alloclen += addrsize;
1134 1134  
1135 1135          if (ipsa->ipsa_flags & IPSA_F_PAIRED) {
1136 1136                  paired = B_TRUE;
1137 1137                  alloclen += sizeof (sadb_x_pair_t);
1138 1138                  otherspi = ipsa->ipsa_otherspi;
1139 1139          } else {
1140 1140                  paired = B_FALSE;
1141 1141          }
1142 1142  
1143 1143          /* How 'bout other lifetimes? */
1144 1144          if (ipsa->ipsa_softaddlt != 0 || ipsa->ipsa_softuselt != 0 ||
1145 1145              ipsa->ipsa_softbyteslt != 0 || ipsa->ipsa_softalloc != 0) {
1146 1146                  alloclen += sizeof (sadb_lifetime_t);
1147 1147                  soft = B_TRUE;
1148 1148          }
1149 1149  
1150 1150          if (ipsa->ipsa_hardaddlt != 0 || ipsa->ipsa_harduselt != 0 ||
1151 1151              ipsa->ipsa_hardbyteslt != 0 || ipsa->ipsa_hardalloc != 0) {
1152 1152                  alloclen += sizeof (sadb_lifetime_t);
1153 1153                  hard = B_TRUE;
1154 1154          }
1155 1155  
1156 1156          if (ipsa->ipsa_idleaddlt != 0 || ipsa->ipsa_idleuselt != 0) {
1157 1157                  alloclen += sizeof (sadb_lifetime_t);
1158 1158                  idle = B_TRUE;
1159 1159          } else {
1160 1160                  idle = B_FALSE;
1161 1161          }
1162 1162  
1163 1163          /* Inner addresses. */
1164 1164          if (ipsa->ipsa_innerfam != 0) {
1165 1165                  pfam = ipsa->ipsa_innerfam;
1166 1166                  switch (pfam) {
1167 1167                  case AF_INET6:
1168 1168                          paddrsize = roundup(sizeof (struct sockaddr_in6) +
1169 1169                              sizeof (sadb_address_t), sizeof (uint64_t));
1170 1170                          break;
1171 1171                  case AF_INET:
1172 1172                          paddrsize = roundup(sizeof (struct sockaddr_in) +
1173 1173                              sizeof (sadb_address_t), sizeof (uint64_t));
1174 1174                          break;
1175 1175                  default:
1176 1176                          cmn_err(CE_PANIC,
1177 1177                              "IPsec SADB: Proxy length failure.\n");
1178 1178                          break;
1179 1179                  }
1180 1180                  isrc = B_TRUE;
1181 1181                  idst = B_TRUE;
1182 1182                  alloclen += 2 * paddrsize;
1183 1183          }
1184 1184  
1185 1185          /* For the following fields, assume that length != 0 ==> stuff */
1186 1186          if (ipsa->ipsa_authkeylen != 0) {
1187 1187                  authsize = roundup(sizeof (sadb_key_t) + ipsa->ipsa_authkeylen,
1188 1188                      sizeof (uint64_t));
1189 1189                  alloclen += authsize;
1190 1190                  auth = B_TRUE;
1191 1191          }
1192 1192  
1193 1193          if (ipsa->ipsa_encrkeylen != 0) {
1194 1194                  encrsize = roundup(sizeof (sadb_key_t) + ipsa->ipsa_encrkeylen +
1195 1195                      ipsa->ipsa_nonce_len, sizeof (uint64_t));
1196 1196                  alloclen += encrsize;
1197 1197                  encr = B_TRUE;
1198 1198          } else {
1199 1199                  encr = B_FALSE;
1200 1200          }
1201 1201  
1202 1202          if (ipsa->ipsa_tsl != NULL) {
1203 1203                  senslen = sadb_sens_len_from_label(ipsa->ipsa_tsl);
1204 1204                  alloclen += senslen;
1205 1205                  sensinteg = B_TRUE;
1206 1206          }
1207 1207  
1208 1208          if (ipsa->ipsa_otsl != NULL) {
1209 1209                  osenslen = sadb_sens_len_from_label(ipsa->ipsa_otsl);
1210 1210                  alloclen += osenslen;
1211 1211                  osensinteg = B_TRUE;
1212 1212          }
1213 1213  
1214 1214          /*
1215 1215           * Must use strlen() here for lengths.  Identities use NULL
1216 1216           * pointers to indicate their nonexistence.
1217 1217           */
1218 1218          if (ipsa->ipsa_src_cid != NULL) {
1219 1219                  srcidsize = roundup(sizeof (sadb_ident_t) +
1220 1220                      strlen(ipsa->ipsa_src_cid->ipsid_cid) + 1,
1221 1221                      sizeof (uint64_t));
1222 1222                  alloclen += srcidsize;
1223 1223                  srcid = B_TRUE;
1224 1224          }
1225 1225  
1226 1226          if (ipsa->ipsa_dst_cid != NULL) {
1227 1227                  dstidsize = roundup(sizeof (sadb_ident_t) +
1228 1228                      strlen(ipsa->ipsa_dst_cid->ipsid_cid) + 1,
1229 1229                      sizeof (uint64_t));
1230 1230                  alloclen += dstidsize;
1231 1231                  dstid = B_TRUE;
1232 1232          }
1233 1233  
1234 1234          if ((ipsa->ipsa_kmp != 0) || (ipsa->ipsa_kmc != 0))
1235 1235                  alloclen += sizeof (sadb_x_kmc_t);
1236 1236  
1237 1237          if (ipsa->ipsa_replay != 0) {
1238 1238                  alloclen += sizeof (sadb_x_replay_ctr_t);
1239 1239          }
1240 1240  
1241 1241          /* Make sure the allocation length is a multiple of 8 bytes. */
1242 1242          ASSERT((alloclen & 0x7) == 0);
1243 1243  
1244 1244          /* XXX Possibly make it esballoc, with a bzero-ing free_ftn. */
1245 1245          mp = allocb(alloclen, BPRI_HI);
1246 1246          if (mp == NULL)
1247 1247                  return (NULL);
1248 1248          bzero(mp->b_rptr, alloclen);
1249 1249  
1250 1250          mp->b_wptr += alloclen;
1251 1251          end = mp->b_wptr;
1252 1252          newsamsg = (sadb_msg_t *)mp->b_rptr;
1253 1253          *newsamsg = *samsg;
1254 1254          newsamsg->sadb_msg_len = (uint16_t)SADB_8TO64(alloclen);
1255 1255  
1256 1256          mutex_enter(&ipsa->ipsa_lock);  /* Since I'm grabbing SA fields... */
1257 1257  
1258 1258          newsamsg->sadb_msg_satype = ipsa->ipsa_type;
1259 1259  
1260 1260          assoc = (sadb_sa_t *)(newsamsg + 1);
1261 1261          assoc->sadb_sa_len = SADB_8TO64(sizeof (*assoc));
1262 1262          assoc->sadb_sa_exttype = SADB_EXT_SA;
1263 1263          assoc->sadb_sa_spi = ipsa->ipsa_spi;
1264 1264          assoc->sadb_sa_replay = ipsa->ipsa_replay_wsize;
1265 1265          assoc->sadb_sa_state = ipsa->ipsa_state;
1266 1266          assoc->sadb_sa_auth = ipsa->ipsa_auth_alg;
1267 1267          assoc->sadb_sa_encrypt = ipsa->ipsa_encr_alg;
1268 1268          assoc->sadb_sa_flags = ipsa->ipsa_flags;
1269 1269  
1270 1270          lt = (sadb_lifetime_t *)(assoc + 1);
1271 1271          lt->sadb_lifetime_len = SADB_8TO64(sizeof (*lt));
1272 1272          lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_CURRENT;
1273 1273          /* We do not support the concept. */
1274 1274          lt->sadb_lifetime_allocations = 0;
1275 1275          lt->sadb_lifetime_bytes = ipsa->ipsa_bytes;
1276 1276          lt->sadb_lifetime_addtime = ipsa->ipsa_addtime;
1277 1277          lt->sadb_lifetime_usetime = ipsa->ipsa_usetime;
1278 1278  
1279 1279          if (hard) {
1280 1280                  lt++;
1281 1281                  lt->sadb_lifetime_len = SADB_8TO64(sizeof (*lt));
1282 1282                  lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
1283 1283                  lt->sadb_lifetime_allocations = ipsa->ipsa_hardalloc;
1284 1284                  lt->sadb_lifetime_bytes = ipsa->ipsa_hardbyteslt;
1285 1285                  lt->sadb_lifetime_addtime = ipsa->ipsa_hardaddlt;
1286 1286                  lt->sadb_lifetime_usetime = ipsa->ipsa_harduselt;
1287 1287          }
1288 1288  
1289 1289          if (soft) {
1290 1290                  lt++;
1291 1291                  lt->sadb_lifetime_len = SADB_8TO64(sizeof (*lt));
1292 1292                  lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
1293 1293                  lt->sadb_lifetime_allocations = ipsa->ipsa_softalloc;
1294 1294                  lt->sadb_lifetime_bytes = ipsa->ipsa_softbyteslt;
1295 1295                  lt->sadb_lifetime_addtime = ipsa->ipsa_softaddlt;
1296 1296                  lt->sadb_lifetime_usetime = ipsa->ipsa_softuselt;
1297 1297          }
1298 1298  
1299 1299          if (idle) {
1300 1300                  lt++;
1301 1301                  lt->sadb_lifetime_len = SADB_8TO64(sizeof (*lt));
1302 1302                  lt->sadb_lifetime_exttype = SADB_X_EXT_LIFETIME_IDLE;
1303 1303                  lt->sadb_lifetime_addtime = ipsa->ipsa_idleaddlt;
1304 1304                  lt->sadb_lifetime_usetime = ipsa->ipsa_idleuselt;
1305 1305          }
1306 1306  
1307 1307          cur = (uint8_t *)(lt + 1);
1308 1308  
1309 1309          /* NOTE:  Don't fill in ports here if we are a tunnel-mode SA. */
1310 1310          cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_SRC, fam,
1311 1311              ipsa->ipsa_srcaddr, (!isrc && !idst) ? SA_SRCPORT(ipsa) : 0,
1312 1312              SA_PROTO(ipsa), 0);
1313 1313          if (cur == NULL) {
1314 1314                  freemsg(mp);
1315 1315                  mp = NULL;
1316 1316                  goto bail;
1317 1317          }
1318 1318  
1319 1319          cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_DST, fam,
1320 1320              ipsa->ipsa_dstaddr, (!isrc && !idst) ? SA_DSTPORT(ipsa) : 0,
1321 1321              SA_PROTO(ipsa), 0);
1322 1322          if (cur == NULL) {
1323 1323                  freemsg(mp);
1324 1324                  mp = NULL;
1325 1325                  goto bail;
1326 1326          }
1327 1327  
1328 1328          if (ipsa->ipsa_flags & IPSA_F_NATT_LOC) {
1329 1329                  cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_NATT_LOC,
1330 1330                      fam, &ipsa->ipsa_natt_addr_loc, ipsa->ipsa_local_nat_port,
1331 1331                      IPPROTO_UDP, 0);
1332 1332                  if (cur == NULL) {
1333 1333                          freemsg(mp);
1334 1334                          mp = NULL;
1335 1335                          goto bail;
1336 1336                  }
1337 1337          }
1338 1338  
1339 1339          if (ipsa->ipsa_flags & IPSA_F_NATT_REM) {
1340 1340                  cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_NATT_REM,
1341 1341                      fam, &ipsa->ipsa_natt_addr_rem, ipsa->ipsa_remote_nat_port,
1342 1342                      IPPROTO_UDP, 0);
1343 1343                  if (cur == NULL) {
1344 1344                          freemsg(mp);
1345 1345                          mp = NULL;
1346 1346                          goto bail;
1347 1347                  }
1348 1348          }
1349 1349  
1350 1350          /* If we are a tunnel-mode SA, fill in the inner-selectors. */
1351 1351          if (isrc) {
1352 1352                  cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_SRC,
1353 1353                      pfam, ipsa->ipsa_innersrc, SA_SRCPORT(ipsa),
1354 1354                      SA_IPROTO(ipsa), ipsa->ipsa_innersrcpfx);
1355 1355                  if (cur == NULL) {
1356 1356                          freemsg(mp);
1357 1357                          mp = NULL;
1358 1358                          goto bail;
1359 1359                  }
1360 1360          }
1361 1361  
1362 1362          if (idst) {
1363 1363                  cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_DST,
1364 1364                      pfam, ipsa->ipsa_innerdst, SA_DSTPORT(ipsa),
1365 1365                      SA_IPROTO(ipsa), ipsa->ipsa_innerdstpfx);
1366 1366                  if (cur == NULL) {
1367 1367                          freemsg(mp);
1368 1368                          mp = NULL;
1369 1369                          goto bail;
1370 1370                  }
1371 1371          }
1372 1372  
1373 1373          if ((ipsa->ipsa_kmp != 0) || (ipsa->ipsa_kmc != 0)) {
1374 1374                  cur = sadb_make_kmc_ext(cur, end,
1375 1375                      ipsa->ipsa_kmp, ipsa->ipsa_kmc);
1376 1376                  if (cur == NULL) {
1377 1377                          freemsg(mp);
1378 1378                          mp = NULL;
1379 1379                          goto bail;
1380 1380                  }
1381 1381          }
1382 1382  
1383 1383          walker = (sadb_ext_t *)cur;
1384 1384          if (auth) {
1385 1385                  key = (sadb_key_t *)walker;
1386 1386                  key->sadb_key_len = SADB_8TO64(authsize);
1387 1387                  key->sadb_key_exttype = SADB_EXT_KEY_AUTH;
1388 1388                  key->sadb_key_bits = ipsa->ipsa_authkeybits;
1389 1389                  key->sadb_key_reserved = 0;
1390 1390                  bcopy(ipsa->ipsa_authkey, key + 1, ipsa->ipsa_authkeylen);
1391 1391                  walker = (sadb_ext_t *)((uint64_t *)walker +
1392 1392                      walker->sadb_ext_len);
1393 1393          }
1394 1394  
1395 1395          if (encr) {
1396 1396                  uint8_t *buf_ptr;
1397 1397                  key = (sadb_key_t *)walker;
1398 1398                  key->sadb_key_len = SADB_8TO64(encrsize);
1399 1399                  key->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
1400 1400                  key->sadb_key_bits = ipsa->ipsa_encrkeybits;
1401 1401                  key->sadb_key_reserved = ipsa->ipsa_saltbits;
1402 1402                  buf_ptr = (uint8_t *)(key + 1);
1403 1403                  bcopy(ipsa->ipsa_encrkey, buf_ptr, ipsa->ipsa_encrkeylen);
1404 1404                  if (ipsa->ipsa_salt != NULL) {
1405 1405                          buf_ptr += ipsa->ipsa_encrkeylen;
1406 1406                          bcopy(ipsa->ipsa_salt, buf_ptr, ipsa->ipsa_saltlen);
1407 1407                  }
1408 1408                  walker = (sadb_ext_t *)((uint64_t *)walker +
1409 1409                      walker->sadb_ext_len);
1410 1410          }
1411 1411  
1412 1412          if (srcid) {
1413 1413                  ident = (sadb_ident_t *)walker;
1414 1414                  ident->sadb_ident_len = SADB_8TO64(srcidsize);
1415 1415                  ident->sadb_ident_exttype = SADB_EXT_IDENTITY_SRC;
1416 1416                  ident->sadb_ident_type = ipsa->ipsa_src_cid->ipsid_type;
1417 1417                  ident->sadb_ident_id = 0;
1418 1418                  ident->sadb_ident_reserved = 0;
1419 1419                  (void) strcpy((char *)(ident + 1),
1420 1420                      ipsa->ipsa_src_cid->ipsid_cid);
1421 1421                  walker = (sadb_ext_t *)((uint64_t *)walker +
1422 1422                      walker->sadb_ext_len);
1423 1423          }
1424 1424  
1425 1425          if (dstid) {
1426 1426                  ident = (sadb_ident_t *)walker;
1427 1427                  ident->sadb_ident_len = SADB_8TO64(dstidsize);
1428 1428                  ident->sadb_ident_exttype = SADB_EXT_IDENTITY_DST;
1429 1429                  ident->sadb_ident_type = ipsa->ipsa_dst_cid->ipsid_type;
1430 1430                  ident->sadb_ident_id = 0;
1431 1431                  ident->sadb_ident_reserved = 0;
1432 1432                  (void) strcpy((char *)(ident + 1),
1433 1433                      ipsa->ipsa_dst_cid->ipsid_cid);
1434 1434                  walker = (sadb_ext_t *)((uint64_t *)walker +
1435 1435                      walker->sadb_ext_len);
1436 1436          }
1437 1437  
1438 1438          if (sensinteg) {
1439 1439                  sens = (sadb_sens_t *)walker;
1440 1440                  sadb_sens_from_label(sens, SADB_EXT_SENSITIVITY,
1441 1441                      ipsa->ipsa_tsl, senslen);
1442 1442  
1443 1443                  walker = (sadb_ext_t *)((uint64_t *)walker +
1444 1444                      walker->sadb_ext_len);
1445 1445          }
1446 1446  
1447 1447          if (osensinteg) {
1448 1448                  sens = (sadb_sens_t *)walker;
1449 1449  
1450 1450                  sadb_sens_from_label(sens, SADB_X_EXT_OUTER_SENS,
1451 1451                      ipsa->ipsa_otsl, osenslen);
1452 1452                  if (ipsa->ipsa_mac_exempt)
1453 1453                          sens->sadb_x_sens_flags = SADB_X_SENS_IMPLICIT;
1454 1454  
1455 1455                  walker = (sadb_ext_t *)((uint64_t *)walker +
1456 1456                      walker->sadb_ext_len);
1457 1457          }
1458 1458  
1459 1459          if (paired) {
1460 1460                  pair_ext = (sadb_x_pair_t *)walker;
1461 1461  
1462 1462                  pair_ext->sadb_x_pair_len = SADB_8TO64(sizeof (sadb_x_pair_t));
1463 1463                  pair_ext->sadb_x_pair_exttype = SADB_X_EXT_PAIR;
1464 1464                  pair_ext->sadb_x_pair_spi = otherspi;
1465 1465  
1466 1466                  walker = (sadb_ext_t *)((uint64_t *)walker +
1467 1467                      walker->sadb_ext_len);
1468 1468          }
1469 1469  
1470 1470          if (ipsa->ipsa_replay != 0) {
1471 1471                  repl_ctr = (sadb_x_replay_ctr_t *)walker;
1472 1472                  repl_ctr->sadb_x_rc_len = SADB_8TO64(sizeof (*repl_ctr));
1473 1473                  repl_ctr->sadb_x_rc_exttype = SADB_X_EXT_REPLAY_VALUE;
1474 1474                  repl_ctr->sadb_x_rc_replay32 = ipsa->ipsa_replay;
1475 1475                  repl_ctr->sadb_x_rc_replay64 = 0;
1476 1476                  walker = (sadb_ext_t *)(repl_ctr + 1);
1477 1477          }
1478 1478  
1479 1479  bail:
1480 1480          /* Pardon any delays... */
1481 1481          mutex_exit(&ipsa->ipsa_lock);
1482 1482  
1483 1483          return (mp);
1484 1484  }
1485 1485  
1486 1486  /*
1487 1487   * Strip out key headers or unmarked headers (SADB_EXT_KEY_*, SADB_EXT_UNKNOWN)
1488 1488   * and adjust base message accordingly.
1489 1489   *
1490 1490   * Assume message is pulled up in one piece of contiguous memory.
1491 1491   *
1492 1492   * Say if we start off with:
1493 1493   *
1494 1494   * +------+----+-------------+-----------+---------------+---------------+
1495 1495   * | base | SA | source addr | dest addr | rsrvd. or key | soft lifetime |
1496 1496   * +------+----+-------------+-----------+---------------+---------------+
1497 1497   *
1498 1498   * we will end up with
1499 1499   *
1500 1500   * +------+----+-------------+-----------+---------------+
1501 1501   * | base | SA | source addr | dest addr | soft lifetime |
1502 1502   * +------+----+-------------+-----------+---------------+
1503 1503   */
1504 1504  static void
1505 1505  sadb_strip(sadb_msg_t *samsg)
1506 1506  {
1507 1507          sadb_ext_t *ext;
1508 1508          uint8_t *target = NULL;
1509 1509          uint8_t *msgend;
1510 1510          int sofar = SADB_8TO64(sizeof (*samsg));
1511 1511          int copylen;
1512 1512  
1513 1513          ext = (sadb_ext_t *)(samsg + 1);
1514 1514          msgend = (uint8_t *)samsg;
1515 1515          msgend += SADB_64TO8(samsg->sadb_msg_len);
1516 1516          while ((uint8_t *)ext < msgend) {
1517 1517                  if (ext->sadb_ext_type == SADB_EXT_RESERVED ||
1518 1518                      ext->sadb_ext_type == SADB_EXT_KEY_AUTH ||
1519 1519                      ext->sadb_ext_type == SADB_X_EXT_EDUMP ||
1520 1520                      ext->sadb_ext_type == SADB_EXT_KEY_ENCRYPT) {
1521 1521                          /*
1522 1522                           * Aha!  I found a header to be erased.
1523 1523                           */
1524 1524  
1525 1525                          if (target != NULL) {
1526 1526                                  /*
1527 1527                                   * If I had a previous header to be erased,
1528 1528                                   * copy over it.  I can get away with just
1529 1529                                   * copying backwards because the target will
1530 1530                                   * always be 8 bytes behind the source.
1531 1531                                   */
1532 1532                                  copylen = ((uint8_t *)ext) - (target +
1533 1533                                      SADB_64TO8(
1534 1534                                      ((sadb_ext_t *)target)->sadb_ext_len));
1535 1535                                  ovbcopy(((uint8_t *)ext - copylen), target,
1536 1536                                      copylen);
1537 1537                                  target += copylen;
1538 1538                                  ((sadb_ext_t *)target)->sadb_ext_len =
1539 1539                                      SADB_8TO64(((uint8_t *)ext) - target +
1540 1540                                      SADB_64TO8(ext->sadb_ext_len));
1541 1541                          } else {
1542 1542                                  target = (uint8_t *)ext;
1543 1543                          }
1544 1544                  } else {
1545 1545                          sofar += ext->sadb_ext_len;
1546 1546                  }
1547 1547  
1548 1548                  ext = (sadb_ext_t *)(((uint64_t *)ext) + ext->sadb_ext_len);
1549 1549          }
1550 1550  
1551 1551          ASSERT((uint8_t *)ext == msgend);
1552 1552  
1553 1553          if (target != NULL) {
1554 1554                  copylen = ((uint8_t *)ext) - (target +
1555 1555                      SADB_64TO8(((sadb_ext_t *)target)->sadb_ext_len));
1556 1556                  if (copylen != 0)
1557 1557                          ovbcopy(((uint8_t *)ext - copylen), target, copylen);
1558 1558          }
1559 1559  
1560 1560          /* Adjust samsg. */
1561 1561          samsg->sadb_msg_len = (uint16_t)sofar;
1562 1562  
1563 1563          /* Assume all of the rest is cleared by caller in sadb_pfkey_echo(). */
1564 1564  }
1565 1565  
1566 1566  /*
1567 1567   * AH needs to send an error to PF_KEY.  Assume mp points to an M_CTL
1568 1568   * followed by an M_DATA with a PF_KEY message in it.  The serial of
1569 1569   * the sending keysock instance is included.
1570 1570   */
1571 1571  void
1572 1572  sadb_pfkey_error(queue_t *pfkey_q, mblk_t *mp, int error, int diagnostic,
1573 1573      uint_t serial)
1574 1574  {
1575 1575          mblk_t *msg = mp->b_cont;
1576 1576          sadb_msg_t *samsg;
1577 1577          keysock_out_t *kso;
1578 1578  
1579 1579          /*
1580 1580           * Enough functions call this to merit a NULL queue check.
1581 1581           */
1582 1582          if (pfkey_q == NULL) {
1583 1583                  freemsg(mp);
1584 1584                  return;
1585 1585          }
1586 1586  
1587 1587          ASSERT(msg != NULL);
1588 1588          ASSERT((mp->b_wptr - mp->b_rptr) == sizeof (ipsec_info_t));
1589 1589          ASSERT((msg->b_wptr - msg->b_rptr) >= sizeof (sadb_msg_t));
1590 1590          samsg = (sadb_msg_t *)msg->b_rptr;
1591 1591          kso = (keysock_out_t *)mp->b_rptr;
1592 1592  
1593 1593          kso->ks_out_type = KEYSOCK_OUT;
1594 1594          kso->ks_out_len = sizeof (*kso);
1595 1595          kso->ks_out_serial = serial;
1596 1596  
1597 1597          /*
1598 1598           * Only send the base message up in the event of an error.
1599 1599           * Don't worry about bzero()-ing, because it was probably bogus
1600 1600           * anyway.
1601 1601           */
1602 1602          msg->b_wptr = msg->b_rptr + sizeof (*samsg);
1603 1603          samsg = (sadb_msg_t *)msg->b_rptr;
1604 1604          samsg->sadb_msg_len = SADB_8TO64(sizeof (*samsg));
1605 1605          samsg->sadb_msg_errno = (uint8_t)error;
1606 1606          if (diagnostic != SADB_X_DIAGNOSTIC_PRESET)
1607 1607                  samsg->sadb_x_msg_diagnostic = (uint16_t)diagnostic;
1608 1608  
1609 1609          putnext(pfkey_q, mp);
1610 1610  }
1611 1611  
1612 1612  /*
1613 1613   * Send a successful return packet back to keysock via the queue in pfkey_q.
1614 1614   *
1615 1615   * Often, an SA is associated with the reply message, it's passed in if needed,
1616 1616   * and NULL if not.  BTW, that ipsa will have its refcnt appropriately held,
1617 1617   * and the caller will release said refcnt.
1618 1618   */
1619 1619  void
1620 1620  sadb_pfkey_echo(queue_t *pfkey_q, mblk_t *mp, sadb_msg_t *samsg,
1621 1621      keysock_in_t *ksi, ipsa_t *ipsa)
1622 1622  {
1623 1623          keysock_out_t *kso;
1624 1624          mblk_t *mp1;
1625 1625          sadb_msg_t *newsamsg;
1626 1626          uint8_t *oldend;
1627 1627  
1628 1628          ASSERT((mp->b_cont != NULL) &&
1629 1629              ((void *)samsg == (void *)mp->b_cont->b_rptr) &&
1630 1630              ((void *)mp->b_rptr == (void *)ksi));
1631 1631  
1632 1632          switch (samsg->sadb_msg_type) {
1633 1633          case SADB_ADD:
1634 1634          case SADB_UPDATE:
1635 1635          case SADB_X_UPDATEPAIR:
1636 1636          case SADB_X_DELPAIR_STATE:
1637 1637          case SADB_FLUSH:
1638 1638          case SADB_DUMP:
1639 1639                  /*
1640 1640                   * I have all of the message already.  I just need to strip
1641 1641                   * out the keying material and echo the message back.
1642 1642                   *
1643 1643                   * NOTE: for SADB_DUMP, the function sadb_dump() did the
1644 1644                   * work.  When DUMP reaches here, it should only be a base
1645 1645                   * message.
1646 1646                   */
1647 1647          justecho:
1648 1648                  if (ksi->ks_in_extv[SADB_EXT_KEY_AUTH] != NULL ||
1649 1649                      ksi->ks_in_extv[SADB_EXT_KEY_ENCRYPT] != NULL ||
1650 1650                      ksi->ks_in_extv[SADB_X_EXT_EDUMP] != NULL) {
1651 1651                          sadb_strip(samsg);
1652 1652                          /* Assume PF_KEY message is contiguous. */
1653 1653                          ASSERT(mp->b_cont->b_cont == NULL);
1654 1654                          oldend = mp->b_cont->b_wptr;
1655 1655                          mp->b_cont->b_wptr = mp->b_cont->b_rptr +
1656 1656                              SADB_64TO8(samsg->sadb_msg_len);
1657 1657                          bzero(mp->b_cont->b_wptr, oldend - mp->b_cont->b_wptr);
1658 1658                  }
1659 1659                  break;
1660 1660          case SADB_GET:
1661 1661                  /*
1662 1662                   * Do a lot of work here, because of the ipsa I just found.
1663 1663                   * First construct the new PF_KEY message, then abandon
1664 1664                   * the old one.
1665 1665                   */
1666 1666                  mp1 = sadb_sa2msg(ipsa, samsg);
1667 1667                  if (mp1 == NULL) {
1668 1668                          sadb_pfkey_error(pfkey_q, mp, ENOMEM,
1669 1669                              SADB_X_DIAGNOSTIC_NONE, ksi->ks_in_serial);
1670 1670                          return;
1671 1671                  }
1672 1672                  freemsg(mp->b_cont);
1673 1673                  mp->b_cont = mp1;
1674 1674                  break;
1675 1675          case SADB_DELETE:
1676 1676          case SADB_X_DELPAIR:
1677 1677                  if (ipsa == NULL)
1678 1678                          goto justecho;
1679 1679                  /*
1680 1680                   * Because listening KMds may require more info, treat
1681 1681                   * DELETE like a special case of GET.
1682 1682                   */
1683 1683                  mp1 = sadb_sa2msg(ipsa, samsg);
1684 1684                  if (mp1 == NULL) {
1685 1685                          sadb_pfkey_error(pfkey_q, mp, ENOMEM,
1686 1686                              SADB_X_DIAGNOSTIC_NONE, ksi->ks_in_serial);
1687 1687                          return;
1688 1688                  }
1689 1689                  newsamsg = (sadb_msg_t *)mp1->b_rptr;
1690 1690                  sadb_strip(newsamsg);
1691 1691                  oldend = mp1->b_wptr;
1692 1692                  mp1->b_wptr = mp1->b_rptr + SADB_64TO8(newsamsg->sadb_msg_len);
1693 1693                  bzero(mp1->b_wptr, oldend - mp1->b_wptr);
1694 1694                  freemsg(mp->b_cont);
1695 1695                  mp->b_cont = mp1;
1696 1696                  break;
1697 1697          default:
1698 1698                  if (mp != NULL)
1699 1699                          freemsg(mp);
1700 1700                  return;
1701 1701          }
1702 1702  
1703 1703          /* ksi is now null and void. */
1704 1704          kso = (keysock_out_t *)ksi;
1705 1705          kso->ks_out_type = KEYSOCK_OUT;
1706 1706          kso->ks_out_len = sizeof (*kso);
1707 1707          kso->ks_out_serial = ksi->ks_in_serial;
1708 1708          /* We're ready to send... */
1709 1709          putnext(pfkey_q, mp);
1710 1710  }
1711 1711  
1712 1712  /*
1713 1713   * Set up a global pfkey_q instance for AH, ESP, or some other consumer.
1714 1714   */
1715 1715  void
1716 1716  sadb_keysock_hello(queue_t **pfkey_qp, queue_t *q, mblk_t *mp,
1717 1717      void (*ager)(void *), void *agerarg, timeout_id_t *top, int satype)
1718 1718  {
1719 1719          keysock_hello_ack_t *kha;
1720 1720          queue_t *oldq;
1721 1721  
1722 1722          ASSERT(OTHERQ(q) != NULL);
1723 1723  
1724 1724          /*
1725 1725           * First, check atomically that I'm the first and only keysock
1726 1726           * instance.
1727 1727           *
1728 1728           * Use OTHERQ(q), because qreply(q, mp) == putnext(OTHERQ(q), mp),
1729 1729           * and I want this module to say putnext(*_pfkey_q, mp) for PF_KEY
1730 1730           * messages.
1731 1731           */
1732 1732  
1733 1733          oldq = atomic_cas_ptr((void **)pfkey_qp, NULL, OTHERQ(q));
1734 1734          if (oldq != NULL) {
1735 1735                  ASSERT(oldq != q);
1736 1736                  cmn_err(CE_WARN, "Danger!  Multiple keysocks on top of %s.\n",
1737 1737                      (satype == SADB_SATYPE_ESP)? "ESP" : "AH or other");
1738 1738                  freemsg(mp);
1739 1739                  return;
1740 1740          }
1741 1741  
1742 1742          kha = (keysock_hello_ack_t *)mp->b_rptr;
1743 1743          kha->ks_hello_len = sizeof (keysock_hello_ack_t);
1744 1744          kha->ks_hello_type = KEYSOCK_HELLO_ACK;
1745 1745          kha->ks_hello_satype = (uint8_t)satype;
1746 1746  
1747 1747          /*
1748 1748           * If we made it past the atomic_cas_ptr, then we have "exclusive"
1749 1749           * access to the timeout handle.  Fire it off after the default ager
1750 1750           * interval.
1751 1751           */
1752 1752          *top = qtimeout(*pfkey_qp, ager, agerarg,
1753 1753              drv_usectohz(SADB_AGE_INTERVAL_DEFAULT * 1000));
1754 1754  
1755 1755          putnext(*pfkey_qp, mp);
1756 1756  }
1757 1757  
1758 1758  /*
1759 1759   * Normalize IPv4-mapped IPv6 addresses (and prefixes) as appropriate.
1760 1760   *
1761 1761   * Check addresses themselves for wildcard or multicast.
1762 1762   * Check ire table for local/non-local/broadcast.
1763 1763   */
1764 1764  int
1765 1765  sadb_addrcheck(queue_t *pfkey_q, mblk_t *mp, sadb_ext_t *ext, uint_t serial,
1766 1766      netstack_t *ns)
1767 1767  {
1768 1768          sadb_address_t *addr = (sadb_address_t *)ext;
1769 1769          struct sockaddr_in *sin;
1770 1770          struct sockaddr_in6 *sin6;
1771 1771          int diagnostic, type;
1772 1772          boolean_t normalized = B_FALSE;
1773 1773  
1774 1774          ASSERT(ext != NULL);
1775 1775          ASSERT((ext->sadb_ext_type == SADB_EXT_ADDRESS_SRC) ||
1776 1776              (ext->sadb_ext_type == SADB_EXT_ADDRESS_DST) ||
1777 1777              (ext->sadb_ext_type == SADB_X_EXT_ADDRESS_INNER_SRC) ||
1778 1778              (ext->sadb_ext_type == SADB_X_EXT_ADDRESS_INNER_DST) ||
1779 1779              (ext->sadb_ext_type == SADB_X_EXT_ADDRESS_NATT_LOC) ||
1780 1780              (ext->sadb_ext_type == SADB_X_EXT_ADDRESS_NATT_REM));
1781 1781  
1782 1782          /* Assign both sockaddrs, the compiler will do the right thing. */
1783 1783          sin = (struct sockaddr_in *)(addr + 1);
1784 1784          sin6 = (struct sockaddr_in6 *)(addr + 1);
1785 1785  
1786 1786          if (sin6->sin6_family == AF_INET6) {
1787 1787                  if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
1788 1788                          /*
1789 1789                           * Convert to an AF_INET sockaddr.  This means the
1790 1790                           * return messages will have the extra space, but have
1791 1791                           * AF_INET sockaddrs instead of AF_INET6.
1792 1792                           *
1793 1793                           * Yes, RFC 2367 isn't clear on what to do here w.r.t.
1794 1794                           * mapped addresses, but since AF_INET6 ::ffff:<v4> is
1795 1795                           * equal to AF_INET <v4>, it shouldnt be a huge
1796 1796                           * problem.
1797 1797                           */
1798 1798                          sin->sin_family = AF_INET;
1799 1799                          IN6_V4MAPPED_TO_INADDR(&sin6->sin6_addr,
1800 1800                              &sin->sin_addr);
1801 1801                          bzero(&sin->sin_zero, sizeof (sin->sin_zero));
1802 1802                          normalized = B_TRUE;
1803 1803                  }
1804 1804          } else if (sin->sin_family != AF_INET) {
1805 1805                  switch (ext->sadb_ext_type) {
1806 1806                  case SADB_EXT_ADDRESS_SRC:
1807 1807                          diagnostic = SADB_X_DIAGNOSTIC_BAD_SRC_AF;
1808 1808                          break;
1809 1809                  case SADB_EXT_ADDRESS_DST:
1810 1810                          diagnostic = SADB_X_DIAGNOSTIC_BAD_DST_AF;
1811 1811                          break;
1812 1812                  case SADB_X_EXT_ADDRESS_INNER_SRC:
1813 1813                          diagnostic = SADB_X_DIAGNOSTIC_BAD_PROXY_AF;
1814 1814                          break;
1815 1815                  case SADB_X_EXT_ADDRESS_INNER_DST:
1816 1816                          diagnostic = SADB_X_DIAGNOSTIC_BAD_INNER_DST_AF;
1817 1817                          break;
1818 1818                  case SADB_X_EXT_ADDRESS_NATT_LOC:
1819 1819                          diagnostic = SADB_X_DIAGNOSTIC_BAD_NATT_LOC_AF;
1820 1820                          break;
1821 1821                  case SADB_X_EXT_ADDRESS_NATT_REM:
1822 1822                          diagnostic = SADB_X_DIAGNOSTIC_BAD_NATT_REM_AF;
1823 1823                          break;
1824 1824                          /* There is no default, see above ASSERT. */
1825 1825                  }
1826 1826  bail:
1827 1827                  if (pfkey_q != NULL) {
1828 1828                          sadb_pfkey_error(pfkey_q, mp, EINVAL, diagnostic,
1829 1829                              serial);
1830 1830                  } else {
1831 1831                          /*
1832 1832                           * Scribble in sadb_msg that we got passed in.
1833 1833                           * Overload "mp" to be an sadb_msg pointer.
1834 1834                           */
1835 1835                          sadb_msg_t *samsg = (sadb_msg_t *)mp;
1836 1836  
1837 1837                          samsg->sadb_msg_errno = EINVAL;
1838 1838                          samsg->sadb_x_msg_diagnostic = diagnostic;
1839 1839                  }
1840 1840                  return (KS_IN_ADDR_UNKNOWN);
1841 1841          }
1842 1842  
1843 1843          if (ext->sadb_ext_type == SADB_X_EXT_ADDRESS_INNER_SRC ||
1844 1844              ext->sadb_ext_type == SADB_X_EXT_ADDRESS_INNER_DST) {
1845 1845                  /*
1846 1846                   * We need only check for prefix issues.
1847 1847                   */
1848 1848  
1849 1849                  /* Set diagnostic now, in case we need it later. */
1850 1850                  diagnostic =
1851 1851                      (ext->sadb_ext_type == SADB_X_EXT_ADDRESS_INNER_SRC) ?
1852 1852                      SADB_X_DIAGNOSTIC_PREFIX_INNER_SRC :
1853 1853                      SADB_X_DIAGNOSTIC_PREFIX_INNER_DST;
1854 1854  
1855 1855                  if (normalized)
1856 1856                          addr->sadb_address_prefixlen -= 96;
1857 1857  
1858 1858                  /*
1859 1859                   * Verify and mask out inner-addresses based on prefix length.
1860 1860                   */
1861 1861                  if (sin->sin_family == AF_INET) {
1862 1862                          if (addr->sadb_address_prefixlen > 32)
1863 1863                                  goto bail;
1864 1864                          sin->sin_addr.s_addr &=
1865 1865                              ip_plen_to_mask(addr->sadb_address_prefixlen);
1866 1866                  } else {
1867 1867                          in6_addr_t mask;
1868 1868  
1869 1869                          ASSERT(sin->sin_family == AF_INET6);
1870 1870                          /*
1871 1871                           * ip_plen_to_mask_v6() returns NULL if the value in
1872 1872                           * question is out of range.
1873 1873                           */
1874 1874                          if (ip_plen_to_mask_v6(addr->sadb_address_prefixlen,
1875 1875                              &mask) == NULL)
1876 1876                                  goto bail;
1877 1877                          sin6->sin6_addr.s6_addr32[0] &= mask.s6_addr32[0];
1878 1878                          sin6->sin6_addr.s6_addr32[1] &= mask.s6_addr32[1];
1879 1879                          sin6->sin6_addr.s6_addr32[2] &= mask.s6_addr32[2];
1880 1880                          sin6->sin6_addr.s6_addr32[3] &= mask.s6_addr32[3];
1881 1881                  }
1882 1882  
1883 1883                  /* We don't care in these cases. */
1884 1884                  return (KS_IN_ADDR_DONTCARE);
1885 1885          }
1886 1886  
1887 1887          if (sin->sin_family == AF_INET6) {
1888 1888                  /* Check the easy ones now. */
1889 1889                  if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
1890 1890                          return (KS_IN_ADDR_MBCAST);
1891 1891                  if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
1892 1892                          return (KS_IN_ADDR_UNSPEC);
1893 1893                  /*
1894 1894                   * At this point, we're a unicast IPv6 address.
1895 1895                   *
1896 1896                   * XXX Zones alert -> me/notme decision needs to be tempered
1897 1897                   * by what zone we're in when we go to zone-aware IPsec.
1898 1898                   */
1899 1899                  if (ip_type_v6(&sin6->sin6_addr, ns->netstack_ip) ==
1900 1900                      IRE_LOCAL) {
1901 1901                          /* Hey hey, it's local. */
1902 1902                          return (KS_IN_ADDR_ME);
1903 1903                  }
1904 1904          } else {
1905 1905                  ASSERT(sin->sin_family == AF_INET);
1906 1906                  if (sin->sin_addr.s_addr == INADDR_ANY)
1907 1907                          return (KS_IN_ADDR_UNSPEC);
1908 1908                  if (CLASSD(sin->sin_addr.s_addr))
1909 1909                          return (KS_IN_ADDR_MBCAST);
1910 1910                  /*
1911 1911                   * At this point we're a unicast or broadcast IPv4 address.
1912 1912                   *
1913 1913                   * Check if the address is IRE_BROADCAST or IRE_LOCAL.
1914 1914                   *
1915 1915                   * XXX Zones alert -> me/notme decision needs to be tempered
1916 1916                   * by what zone we're in when we go to zone-aware IPsec.
1917 1917                   */
1918 1918                  type = ip_type_v4(sin->sin_addr.s_addr, ns->netstack_ip);
1919 1919                  switch (type) {
1920 1920                  case IRE_LOCAL:
1921 1921                          return (KS_IN_ADDR_ME);
1922 1922                  case IRE_BROADCAST:
1923 1923                          return (KS_IN_ADDR_MBCAST);
1924 1924                  }
1925 1925          }
1926 1926  
1927 1927          return (KS_IN_ADDR_NOTME);
1928 1928  }
1929 1929  
1930 1930  /*
1931 1931   * Address normalizations and reality checks for inbound PF_KEY messages.
1932 1932   *
1933 1933   * For the case of src == unspecified AF_INET6, and dst == AF_INET, convert
1934 1934   * the source to AF_INET.  Do the same for the inner sources.
1935 1935   */
1936 1936  boolean_t
1937 1937  sadb_addrfix(keysock_in_t *ksi, queue_t *pfkey_q, mblk_t *mp, netstack_t *ns)
1938 1938  {
1939 1939          struct sockaddr_in *src, *isrc;
1940 1940          struct sockaddr_in6 *dst, *idst;
1941 1941          sadb_address_t *srcext, *dstext;
1942 1942          uint16_t sport;
1943 1943          sadb_ext_t **extv = ksi->ks_in_extv;
1944 1944          int rc;
1945 1945  
1946 1946          if (extv[SADB_EXT_ADDRESS_SRC] != NULL) {
1947 1947                  rc = sadb_addrcheck(pfkey_q, mp, extv[SADB_EXT_ADDRESS_SRC],
1948 1948                      ksi->ks_in_serial, ns);
1949 1949                  if (rc == KS_IN_ADDR_UNKNOWN)
1950 1950                          return (B_FALSE);
1951 1951                  if (rc == KS_IN_ADDR_MBCAST) {
1952 1952                          sadb_pfkey_error(pfkey_q, mp, EINVAL,
1953 1953                              SADB_X_DIAGNOSTIC_BAD_SRC, ksi->ks_in_serial);
1954 1954                          return (B_FALSE);
1955 1955                  }
1956 1956                  ksi->ks_in_srctype = rc;
1957 1957          }
1958 1958  
1959 1959          if (extv[SADB_EXT_ADDRESS_DST] != NULL) {
1960 1960                  rc = sadb_addrcheck(pfkey_q, mp, extv[SADB_EXT_ADDRESS_DST],
1961 1961                      ksi->ks_in_serial, ns);
1962 1962                  if (rc == KS_IN_ADDR_UNKNOWN)
1963 1963                          return (B_FALSE);
1964 1964                  if (rc == KS_IN_ADDR_UNSPEC) {
1965 1965                          sadb_pfkey_error(pfkey_q, mp, EINVAL,
1966 1966                              SADB_X_DIAGNOSTIC_BAD_DST, ksi->ks_in_serial);
1967 1967                          return (B_FALSE);
1968 1968                  }
1969 1969                  ksi->ks_in_dsttype = rc;
1970 1970          }
1971 1971  
1972 1972          /*
1973 1973           * NAT-Traversal addrs are simple enough to not require all of
1974 1974           * the checks in sadb_addrcheck().  Just normalize or reject if not
1975 1975           * AF_INET.
1976 1976           */
1977 1977          if (extv[SADB_X_EXT_ADDRESS_NATT_LOC] != NULL) {
1978 1978                  rc = sadb_addrcheck(pfkey_q, mp,
1979 1979                      extv[SADB_X_EXT_ADDRESS_NATT_LOC], ksi->ks_in_serial, ns);
1980 1980  
1981 1981                  /*
1982 1982                   * Local NAT-T addresses never use an IRE_LOCAL, so it should
1983 1983                   * always be NOTME, or UNSPEC (to handle both tunnel mode
1984 1984                   * AND local-port flexibility).
1985 1985                   */
1986 1986                  if (rc != KS_IN_ADDR_NOTME && rc != KS_IN_ADDR_UNSPEC) {
1987 1987                          sadb_pfkey_error(pfkey_q, mp, EINVAL,
1988 1988                              SADB_X_DIAGNOSTIC_MALFORMED_NATT_LOC,
1989 1989                              ksi->ks_in_serial);
1990 1990                          return (B_FALSE);
1991 1991                  }
1992 1992                  src = (struct sockaddr_in *)
1993 1993                      (((sadb_address_t *)extv[SADB_X_EXT_ADDRESS_NATT_LOC]) + 1);
1994 1994                  if (src->sin_family != AF_INET) {
1995 1995                          sadb_pfkey_error(pfkey_q, mp, EINVAL,
1996 1996                              SADB_X_DIAGNOSTIC_BAD_NATT_LOC_AF,
1997 1997                              ksi->ks_in_serial);
1998 1998                          return (B_FALSE);
1999 1999                  }
2000 2000          }
2001 2001  
2002 2002          if (extv[SADB_X_EXT_ADDRESS_NATT_REM] != NULL) {
2003 2003                  rc = sadb_addrcheck(pfkey_q, mp,
2004 2004                      extv[SADB_X_EXT_ADDRESS_NATT_REM], ksi->ks_in_serial, ns);
2005 2005  
2006 2006                  /*
2007 2007                   * Remote NAT-T addresses never use an IRE_LOCAL, so it should
2008 2008                   * always be NOTME, or UNSPEC if it's a tunnel-mode SA.
2009 2009                   */
2010 2010                  if (rc != KS_IN_ADDR_NOTME &&
2011 2011                      !(extv[SADB_X_EXT_ADDRESS_INNER_SRC] != NULL &&
2012 2012                      rc == KS_IN_ADDR_UNSPEC)) {
2013 2013                          sadb_pfkey_error(pfkey_q, mp, EINVAL,
2014 2014                              SADB_X_DIAGNOSTIC_MALFORMED_NATT_REM,
2015 2015                              ksi->ks_in_serial);
2016 2016                          return (B_FALSE);
2017 2017                  }
2018 2018                  src = (struct sockaddr_in *)
2019 2019                      (((sadb_address_t *)extv[SADB_X_EXT_ADDRESS_NATT_REM]) + 1);
2020 2020                  if (src->sin_family != AF_INET) {
2021 2021                          sadb_pfkey_error(pfkey_q, mp, EINVAL,
2022 2022                              SADB_X_DIAGNOSTIC_BAD_NATT_REM_AF,
2023 2023                              ksi->ks_in_serial);
2024 2024                          return (B_FALSE);
2025 2025                  }
2026 2026          }
2027 2027  
2028 2028          if (extv[SADB_X_EXT_ADDRESS_INNER_SRC] != NULL) {
2029 2029                  if (extv[SADB_X_EXT_ADDRESS_INNER_DST] == NULL) {
2030 2030                          sadb_pfkey_error(pfkey_q, mp, EINVAL,
2031 2031                              SADB_X_DIAGNOSTIC_MISSING_INNER_DST,
2032 2032                              ksi->ks_in_serial);
2033 2033                          return (B_FALSE);
2034 2034                  }
2035 2035  
2036 2036                  if (sadb_addrcheck(pfkey_q, mp,
2037 2037                      extv[SADB_X_EXT_ADDRESS_INNER_DST], ksi->ks_in_serial, ns)
2038 2038                      == KS_IN_ADDR_UNKNOWN ||
2039 2039                      sadb_addrcheck(pfkey_q, mp,
2040 2040                      extv[SADB_X_EXT_ADDRESS_INNER_SRC], ksi->ks_in_serial, ns)
2041 2041                      == KS_IN_ADDR_UNKNOWN)
2042 2042                          return (B_FALSE);
2043 2043  
2044 2044                  isrc = (struct sockaddr_in *)
2045 2045                      (((sadb_address_t *)extv[SADB_X_EXT_ADDRESS_INNER_SRC]) +
2046 2046                      1);
2047 2047                  idst = (struct sockaddr_in6 *)
2048 2048                      (((sadb_address_t *)extv[SADB_X_EXT_ADDRESS_INNER_DST]) +
2049 2049                      1);
2050 2050                  if (isrc->sin_family != idst->sin6_family) {
2051 2051                          sadb_pfkey_error(pfkey_q, mp, EINVAL,
2052 2052                              SADB_X_DIAGNOSTIC_INNER_AF_MISMATCH,
2053 2053                              ksi->ks_in_serial);
2054 2054                          return (B_FALSE);
2055 2055                  }
2056 2056          } else if (extv[SADB_X_EXT_ADDRESS_INNER_DST] != NULL) {
2057 2057                          sadb_pfkey_error(pfkey_q, mp, EINVAL,
2058 2058                              SADB_X_DIAGNOSTIC_MISSING_INNER_SRC,
2059 2059                              ksi->ks_in_serial);
2060 2060                          return (B_FALSE);
2061 2061          } else {
2062 2062                  isrc = NULL;    /* For inner/outer port check below. */
2063 2063          }
2064 2064  
2065 2065          dstext = (sadb_address_t *)extv[SADB_EXT_ADDRESS_DST];
2066 2066          srcext = (sadb_address_t *)extv[SADB_EXT_ADDRESS_SRC];
2067 2067  
2068 2068          if (dstext == NULL || srcext == NULL)
2069 2069                  return (B_TRUE);
2070 2070  
2071 2071          dst = (struct sockaddr_in6 *)(dstext + 1);
2072 2072          src = (struct sockaddr_in *)(srcext + 1);
2073 2073  
2074 2074          if (isrc != NULL &&
2075 2075              (isrc->sin_port != 0 || idst->sin6_port != 0) &&
2076 2076              (src->sin_port != 0 || dst->sin6_port != 0)) {
2077 2077                  /* Can't set inner and outer ports in one SA. */
2078 2078                  sadb_pfkey_error(pfkey_q, mp, EINVAL,
2079 2079                      SADB_X_DIAGNOSTIC_DUAL_PORT_SETS,
2080 2080                      ksi->ks_in_serial);
2081 2081                  return (B_FALSE);
2082 2082          }
2083 2083  
2084 2084          if (dst->sin6_family == src->sin_family)
2085 2085                  return (B_TRUE);
2086 2086  
2087 2087          if (srcext->sadb_address_proto != dstext->sadb_address_proto) {
2088 2088                  if (srcext->sadb_address_proto == 0) {
2089 2089                          srcext->sadb_address_proto = dstext->sadb_address_proto;
2090 2090                  } else if (dstext->sadb_address_proto == 0) {
2091 2091                          dstext->sadb_address_proto = srcext->sadb_address_proto;
2092 2092                  } else {
2093 2093                          /* Inequal protocols, neither were 0.  Report error. */
2094 2094                          sadb_pfkey_error(pfkey_q, mp, EINVAL,
2095 2095                              SADB_X_DIAGNOSTIC_PROTO_MISMATCH,
2096 2096                              ksi->ks_in_serial);
2097 2097                          return (B_FALSE);
2098 2098                  }
2099 2099          }
2100 2100  
2101 2101          /*
2102 2102           * With the exception of an unspec IPv6 source and an IPv4
2103 2103           * destination, address families MUST me matched.
2104 2104           */
2105 2105          if (src->sin_family == AF_INET ||
2106 2106              ksi->ks_in_srctype != KS_IN_ADDR_UNSPEC) {
2107 2107                  sadb_pfkey_error(pfkey_q, mp, EINVAL,
2108 2108                      SADB_X_DIAGNOSTIC_AF_MISMATCH, ksi->ks_in_serial);
2109 2109                  return (B_FALSE);
2110 2110          }
2111 2111  
2112 2112          /*
2113 2113           * Convert "src" to AF_INET INADDR_ANY.  We rely on sin_port being
2114 2114           * in the same place for sockaddr_in and sockaddr_in6.
2115 2115           */
2116 2116          sport = src->sin_port;
2117 2117          bzero(src, sizeof (*src));
2118 2118          src->sin_family = AF_INET;
2119 2119          src->sin_port = sport;
2120 2120  
2121 2121          return (B_TRUE);
2122 2122  }
2123 2123  
2124 2124  /*
2125 2125   * Set the results in "addrtype", given an IRE as requested by
2126 2126   * sadb_addrcheck().
2127 2127   */
2128 2128  int
2129 2129  sadb_addrset(ire_t *ire)
2130 2130  {
2131 2131          if ((ire->ire_type & IRE_BROADCAST) ||
2132 2132              (ire->ire_ipversion == IPV4_VERSION && CLASSD(ire->ire_addr)) ||
2133 2133              (ire->ire_ipversion == IPV6_VERSION &&
2134 2134              IN6_IS_ADDR_MULTICAST(&(ire->ire_addr_v6))))
2135 2135                  return (KS_IN_ADDR_MBCAST);
2136 2136          if (ire->ire_type & (IRE_LOCAL | IRE_LOOPBACK))
2137 2137                  return (KS_IN_ADDR_ME);
2138 2138          return (KS_IN_ADDR_NOTME);
2139 2139  }
2140 2140  
2141 2141  /*
2142 2142   * Match primitives..
2143 2143   * !!! TODO: short term: inner selectors
2144 2144   *              ipv6 scope id (ifindex)
2145 2145   * longer term:  zone id.  sensitivity label. uid.
2146 2146   */
2147 2147  boolean_t
2148 2148  sadb_match_spi(ipsa_query_t *sq, ipsa_t *sa)
2149 2149  {
2150 2150          return (sq->spi == sa->ipsa_spi);
2151 2151  }
2152 2152  
2153 2153  boolean_t
2154 2154  sadb_match_dst_v6(ipsa_query_t *sq, ipsa_t *sa)
2155 2155  {
2156 2156          return (IPSA_ARE_ADDR_EQUAL(sa->ipsa_dstaddr, sq->dstaddr, AF_INET6));
2157 2157  }
2158 2158  
2159 2159  boolean_t
2160 2160  sadb_match_src_v6(ipsa_query_t *sq, ipsa_t *sa)
2161 2161  {
2162 2162          return (IPSA_ARE_ADDR_EQUAL(sa->ipsa_srcaddr, sq->srcaddr, AF_INET6));
2163 2163  }
2164 2164  
2165 2165  boolean_t
2166 2166  sadb_match_dst_v4(ipsa_query_t *sq, ipsa_t *sa)
2167 2167  {
2168 2168          return (sq->dstaddr[0] == sa->ipsa_dstaddr[0]);
2169 2169  }
2170 2170  
2171 2171  boolean_t
2172 2172  sadb_match_src_v4(ipsa_query_t *sq, ipsa_t *sa)
2173 2173  {
2174 2174          return (sq->srcaddr[0] == sa->ipsa_srcaddr[0]);
2175 2175  }
2176 2176  
2177 2177  boolean_t
2178 2178  sadb_match_dstid(ipsa_query_t *sq, ipsa_t *sa)
2179 2179  {
2180 2180          return ((sa->ipsa_dst_cid != NULL) &&
2181 2181              (sq->didtype == sa->ipsa_dst_cid->ipsid_type) &&
2182 2182              (strcmp(sq->didstr, sa->ipsa_dst_cid->ipsid_cid) == 0));
2183 2183  
2184 2184  }
2185 2185  boolean_t
2186 2186  sadb_match_srcid(ipsa_query_t *sq, ipsa_t *sa)
2187 2187  {
2188 2188          return ((sa->ipsa_src_cid != NULL) &&
2189 2189              (sq->sidtype == sa->ipsa_src_cid->ipsid_type) &&
2190 2190              (strcmp(sq->sidstr, sa->ipsa_src_cid->ipsid_cid) == 0));
2191 2191  }
2192 2192  
2193 2193  boolean_t
2194 2194  sadb_match_kmc(ipsa_query_t *sq, ipsa_t *sa)
2195 2195  {
2196 2196  #define M(a, b) (((a) == 0) || ((b) == 0) || ((a) == (b)))
2197 2197  
2198 2198          return (M(sq->kmc, sa->ipsa_kmc) && M(sq->kmp, sa->ipsa_kmp));
2199 2199  
2200 2200  #undef M
2201 2201  }
2202 2202  
2203 2203  /*
2204 2204   * Common function which extracts several PF_KEY extensions for ease of
2205 2205   * SADB matching.
2206 2206   *
2207 2207   * XXX TODO: weed out ipsa_query_t fields not used during matching
2208 2208   * or afterwards?
2209 2209   */
2210 2210  int
2211 2211  sadb_form_query(keysock_in_t *ksi, uint32_t req, uint32_t match,
2212 2212      ipsa_query_t *sq, int *diagnostic)
2213 2213  {
2214 2214          int i;
2215 2215          ipsa_match_fn_t *mfpp = &(sq->matchers[0]);
2216 2216  
2217 2217          for (i = 0; i < IPSA_NMATCH; i++)
2218 2218                  sq->matchers[i] = NULL;
2219 2219  
2220 2220          ASSERT((req & ~match) == 0);
2221 2221  
2222 2222          sq->req = req;
2223 2223          sq->dstext = (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_DST];
2224 2224          sq->srcext = (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_SRC];
2225 2225          sq->assoc = (sadb_sa_t *)ksi->ks_in_extv[SADB_EXT_SA];
2226 2226  
2227 2227          if ((req & IPSA_Q_DST) && (sq->dstext == NULL)) {
2228 2228                  *diagnostic = SADB_X_DIAGNOSTIC_MISSING_DST;
2229 2229                  return (EINVAL);
2230 2230          }
2231 2231          if ((req & IPSA_Q_SRC) && (sq->srcext == NULL)) {
2232 2232                  *diagnostic = SADB_X_DIAGNOSTIC_MISSING_SRC;
2233 2233                  return (EINVAL);
2234 2234          }
2235 2235          if ((req & IPSA_Q_SA) && (sq->assoc == NULL)) {
2236 2236                  *diagnostic = SADB_X_DIAGNOSTIC_MISSING_SA;
2237 2237                  return (EINVAL);
2238 2238          }
2239 2239  
2240 2240          if (match & IPSA_Q_SA) {
2241 2241                  *mfpp++ = sadb_match_spi;
2242 2242                  sq->spi = sq->assoc->sadb_sa_spi;
2243 2243          }
2244 2244  
2245 2245          if (sq->dstext != NULL)
2246 2246                  sq->dst = (struct sockaddr_in *)(sq->dstext + 1);
2247 2247          else {
2248 2248                  sq->dst = NULL;
2249 2249                  sq->dst6 = NULL;
2250 2250                  sq->dstaddr = NULL;
2251 2251          }
2252 2252  
2253 2253          if (sq->srcext != NULL)
2254 2254                  sq->src = (struct sockaddr_in *)(sq->srcext + 1);
2255 2255          else {
2256 2256                  sq->src = NULL;
2257 2257                  sq->src6 = NULL;
2258 2258                  sq->srcaddr = NULL;
2259 2259          }
2260 2260  
2261 2261          if (sq->dst != NULL)
2262 2262                  sq->af = sq->dst->sin_family;
2263 2263          else if (sq->src != NULL)
2264 2264                  sq->af = sq->src->sin_family;
2265 2265          else
2266 2266                  sq->af = AF_INET;
2267 2267  
2268 2268          if (sq->af == AF_INET6) {
2269 2269                  if ((match & IPSA_Q_DST) && (sq->dstext != NULL)) {
2270 2270                          *mfpp++ = sadb_match_dst_v6;
2271 2271                          sq->dst6 = (struct sockaddr_in6 *)sq->dst;
2272 2272                          sq->dstaddr = (uint32_t *)&(sq->dst6->sin6_addr);
2273 2273                  } else {
2274 2274                          match &= ~IPSA_Q_DST;
2275 2275                          sq->dstaddr = ALL_ZEROES_PTR;
2276 2276                  }
2277 2277  
2278 2278                  if ((match & IPSA_Q_SRC) && (sq->srcext != NULL)) {
2279 2279                          sq->src6 = (struct sockaddr_in6 *)(sq->srcext + 1);
2280 2280                          sq->srcaddr = (uint32_t *)&sq->src6->sin6_addr;
2281 2281                          if (sq->src6->sin6_family != AF_INET6) {
2282 2282                                  *diagnostic = SADB_X_DIAGNOSTIC_AF_MISMATCH;
2283 2283                                  return (EINVAL);
2284 2284                          }
2285 2285                          *mfpp++ = sadb_match_src_v6;
2286 2286                  } else {
2287 2287                          match &= ~IPSA_Q_SRC;
2288 2288                          sq->srcaddr = ALL_ZEROES_PTR;
2289 2289                  }
2290 2290          } else {
2291 2291                  sq->src6 = sq->dst6 = NULL;
2292 2292                  if ((match & IPSA_Q_DST) && (sq->dstext != NULL)) {
2293 2293                          *mfpp++ = sadb_match_dst_v4;
2294 2294                          sq->dstaddr = (uint32_t *)&sq->dst->sin_addr;
2295 2295                  } else {
2296 2296                          match &= ~IPSA_Q_DST;
2297 2297                          sq->dstaddr = ALL_ZEROES_PTR;
2298 2298                  }
2299 2299                  if ((match & IPSA_Q_SRC) && (sq->srcext != NULL)) {
2300 2300                          sq->srcaddr = (uint32_t *)&sq->src->sin_addr;
2301 2301                          if (sq->src->sin_family != AF_INET) {
2302 2302                                  *diagnostic = SADB_X_DIAGNOSTIC_AF_MISMATCH;
2303 2303                                  return (EINVAL);
2304 2304                          }
2305 2305                          *mfpp++ = sadb_match_src_v4;
2306 2306                  } else {
2307 2307                          match &= ~IPSA_Q_SRC;
2308 2308                          sq->srcaddr = ALL_ZEROES_PTR;
2309 2309                  }
2310 2310          }
2311 2311  
2312 2312          sq->dstid = (sadb_ident_t *)ksi->ks_in_extv[SADB_EXT_IDENTITY_DST];
2313 2313          if ((match & IPSA_Q_DSTID) && (sq->dstid != NULL)) {
2314 2314                  sq->didstr = (char *)(sq->dstid + 1);
2315 2315                  sq->didtype = sq->dstid->sadb_ident_type;
2316 2316                  *mfpp++ = sadb_match_dstid;
2317 2317          }
2318 2318  
2319 2319          sq->srcid = (sadb_ident_t *)ksi->ks_in_extv[SADB_EXT_IDENTITY_SRC];
2320 2320  
2321 2321          if ((match & IPSA_Q_SRCID) && (sq->srcid != NULL)) {
2322 2322                  sq->sidstr = (char *)(sq->srcid + 1);
  
    | 
      ↓ open down ↓ | 
    2322 lines elided | 
    
      ↑ open up ↑ | 
  
2323 2323                  sq->sidtype = sq->srcid->sadb_ident_type;
2324 2324                  *mfpp++ = sadb_match_srcid;
2325 2325          }
2326 2326  
2327 2327          sq->kmcext = (sadb_x_kmc_t *)ksi->ks_in_extv[SADB_X_EXT_KM_COOKIE];
2328 2328          sq->kmc = 0;
2329 2329          sq->kmp = 0;
2330 2330  
2331 2331          if ((match & IPSA_Q_KMC) && (sq->kmcext)) {
2332 2332                  sq->kmp = sq->kmcext->sadb_x_kmc_proto;
2333      -                /* Be liberal in what we receive.  Special-case IKEv1. */
     2333 +                /*
     2334 +                 * Be liberal in what we receive.  Special-case the IKEv1
     2335 +                 * cookie, which closed-source in.iked assumes is 32 bits.
     2336 +                 * Now that we store all 64 bits, we should pre-zero the
     2337 +                 * reserved field on behalf of closed-source in.iked.
     2338 +                 */
2334 2339                  if (sq->kmp == SADB_X_KMP_IKE) {
2335 2340                          /* Just in case in.iked is misbehaving... */
2336 2341                          sq->kmcext->sadb_x_kmc_reserved = 0;
2337 2342                  }
2338 2343                  sq->kmc = sq->kmcext->sadb_x_kmc_cookie64;
2339 2344                  *mfpp++ = sadb_match_kmc;
2340 2345          }
2341 2346  
2342 2347          if (match & (IPSA_Q_INBOUND|IPSA_Q_OUTBOUND)) {
2343 2348                  if (sq->af == AF_INET6)
2344 2349                          sq->sp = &sq->spp->s_v6;
2345 2350                  else
2346 2351                          sq->sp = &sq->spp->s_v4;
2347 2352          } else {
2348 2353                  sq->sp = NULL;
2349 2354          }
2350 2355  
2351 2356          if (match & IPSA_Q_INBOUND) {
2352 2357                  sq->inhash = INBOUND_HASH(sq->sp, sq->assoc->sadb_sa_spi);
2353 2358                  sq->inbound = &sq->sp->sdb_if[sq->inhash];
2354 2359          } else {
2355 2360                  sq->inhash = 0;
2356 2361                  sq->inbound = NULL;
2357 2362          }
2358 2363  
2359 2364          if (match & IPSA_Q_OUTBOUND) {
2360 2365                  if (sq->af == AF_INET6) {
2361 2366                          sq->outhash = OUTBOUND_HASH_V6(sq->sp, *(sq->dstaddr));
2362 2367                  } else {
2363 2368                          sq->outhash = OUTBOUND_HASH_V4(sq->sp, *(sq->dstaddr));
2364 2369                  }
2365 2370                  sq->outbound = &sq->sp->sdb_of[sq->outhash];
2366 2371          } else {
2367 2372                  sq->outhash = 0;
2368 2373                  sq->outbound = NULL;
2369 2374          }
2370 2375          sq->match = match;
2371 2376          return (0);
2372 2377  }
2373 2378  
2374 2379  /*
2375 2380   * Match an initialized query structure with a security association;
2376 2381   * return B_TRUE on a match, B_FALSE on a miss.
2377 2382   * Applies match functions set up by sadb_form_query() until one returns false.
2378 2383   */
2379 2384  boolean_t
2380 2385  sadb_match_query(ipsa_query_t *sq, ipsa_t *sa)
2381 2386  {
2382 2387          ipsa_match_fn_t *mfpp = &(sq->matchers[0]);
2383 2388          ipsa_match_fn_t mfp;
2384 2389  
2385 2390          for (mfp = *mfpp++; mfp != NULL; mfp = *mfpp++) {
2386 2391                  if (!mfp(sq, sa))
2387 2392                          return (B_FALSE);
2388 2393          }
2389 2394          return (B_TRUE);
2390 2395  }
2391 2396  
2392 2397  /*
2393 2398   * Walker callback function to delete sa's based on src/dst address.
2394 2399   * Assumes that we're called with *head locked, no other locks held;
2395 2400   * Conveniently, and not coincidentally, this is both what sadb_walker
2396 2401   * gives us and also what sadb_unlinkassoc expects.
2397 2402   */
2398 2403  struct sadb_purge_state
2399 2404  {
2400 2405          ipsa_query_t sq;
2401 2406          boolean_t inbnd;
2402 2407          uint8_t sadb_sa_state;
2403 2408  };
2404 2409  
2405 2410  static void
2406 2411  sadb_purge_cb(isaf_t *head, ipsa_t *entry, void *cookie)
2407 2412  {
2408 2413          struct sadb_purge_state *ps = (struct sadb_purge_state *)cookie;
2409 2414  
2410 2415          ASSERT(MUTEX_HELD(&head->isaf_lock));
2411 2416  
2412 2417          mutex_enter(&entry->ipsa_lock);
2413 2418  
2414 2419          if (entry->ipsa_state == IPSA_STATE_LARVAL ||
2415 2420              !sadb_match_query(&ps->sq, entry)) {
2416 2421                  mutex_exit(&entry->ipsa_lock);
2417 2422                  return;
2418 2423          }
2419 2424  
2420 2425          if (ps->inbnd) {
2421 2426                  sadb_delete_cluster(entry);
2422 2427          }
2423 2428          entry->ipsa_state = IPSA_STATE_DEAD;
2424 2429          (void) sadb_torch_assoc(head, entry);
2425 2430  }
2426 2431  
2427 2432  /*
2428 2433   * Common code to purge an SA with a matching src or dst address.
2429 2434   * Don't kill larval SA's in such a purge.
2430 2435   */
2431 2436  int
2432 2437  sadb_purge_sa(mblk_t *mp, keysock_in_t *ksi, sadb_t *sp,
2433 2438      int *diagnostic, queue_t *pfkey_q)
2434 2439  {
2435 2440          struct sadb_purge_state ps;
2436 2441          int error = sadb_form_query(ksi, 0,
2437 2442              IPSA_Q_SRC|IPSA_Q_DST|IPSA_Q_SRCID|IPSA_Q_DSTID|IPSA_Q_KMC,
2438 2443              &ps.sq, diagnostic);
2439 2444  
2440 2445          if (error != 0)
2441 2446                  return (error);
2442 2447  
2443 2448          /*
2444 2449           * This is simple, crude, and effective.
2445 2450           * Unimplemented optimizations (TBD):
2446 2451           * - we can limit how many places we search based on where we
2447 2452           * think the SA is filed.
2448 2453           * - if we get a dst address, we can hash based on dst addr to find
2449 2454           * the correct bucket in the outbound table.
2450 2455           */
2451 2456          ps.inbnd = B_TRUE;
2452 2457          sadb_walker(sp->sdb_if, sp->sdb_hashsize, sadb_purge_cb, &ps);
2453 2458          ps.inbnd = B_FALSE;
2454 2459          sadb_walker(sp->sdb_of, sp->sdb_hashsize, sadb_purge_cb, &ps);
2455 2460  
2456 2461          ASSERT(mp->b_cont != NULL);
2457 2462          sadb_pfkey_echo(pfkey_q, mp, (sadb_msg_t *)mp->b_cont->b_rptr, ksi,
2458 2463              NULL);
2459 2464          return (0);
2460 2465  }
2461 2466  
2462 2467  static void
2463 2468  sadb_delpair_state_one(isaf_t *head, ipsa_t *entry, void *cookie)
2464 2469  {
2465 2470          struct sadb_purge_state *ps = (struct sadb_purge_state *)cookie;
2466 2471          isaf_t  *inbound_bucket;
2467 2472          ipsa_t *peer_assoc;
2468 2473          ipsa_query_t *sq = &ps->sq;
2469 2474  
2470 2475          ASSERT(MUTEX_HELD(&head->isaf_lock));
2471 2476  
2472 2477          mutex_enter(&entry->ipsa_lock);
2473 2478  
2474 2479          if ((entry->ipsa_state != ps->sadb_sa_state) ||
2475 2480              ((sq->srcaddr != NULL) &&
2476 2481              !IPSA_ARE_ADDR_EQUAL(entry->ipsa_srcaddr, sq->srcaddr, sq->af))) {
2477 2482                  mutex_exit(&entry->ipsa_lock);
2478 2483                  return;
2479 2484          }
2480 2485  
2481 2486          /*
2482 2487           * The isaf_t *, which is passed in , is always an outbound bucket,
2483 2488           * and we are preserving the outbound-then-inbound hash-bucket lock
2484 2489           * ordering. The sadb_walker() which triggers this function is called
2485 2490           * only on the outbound fanout, and the corresponding inbound bucket
2486 2491           * lock is safe to acquire here.
2487 2492           */
2488 2493  
2489 2494          if (entry->ipsa_haspeer) {
2490 2495                  inbound_bucket = INBOUND_BUCKET(sq->sp, entry->ipsa_spi);
2491 2496                  mutex_enter(&inbound_bucket->isaf_lock);
2492 2497                  peer_assoc = ipsec_getassocbyspi(inbound_bucket,
2493 2498                      entry->ipsa_spi, entry->ipsa_srcaddr,
2494 2499                      entry->ipsa_dstaddr, entry->ipsa_addrfam);
2495 2500          } else {
2496 2501                  inbound_bucket = INBOUND_BUCKET(sq->sp, entry->ipsa_otherspi);
2497 2502                  mutex_enter(&inbound_bucket->isaf_lock);
2498 2503                  peer_assoc = ipsec_getassocbyspi(inbound_bucket,
2499 2504                      entry->ipsa_otherspi, entry->ipsa_dstaddr,
2500 2505                      entry->ipsa_srcaddr, entry->ipsa_addrfam);
2501 2506          }
2502 2507  
2503 2508          entry->ipsa_state = IPSA_STATE_DEAD;
2504 2509          (void) sadb_torch_assoc(head, entry);
2505 2510          if (peer_assoc != NULL) {
2506 2511                  mutex_enter(&peer_assoc->ipsa_lock);
2507 2512                  peer_assoc->ipsa_state = IPSA_STATE_DEAD;
2508 2513                  (void) sadb_torch_assoc(inbound_bucket, peer_assoc);
2509 2514          }
2510 2515          mutex_exit(&inbound_bucket->isaf_lock);
2511 2516  }
2512 2517  
2513 2518  static int
2514 2519  sadb_delpair_state(mblk_t *mp, keysock_in_t *ksi, sadbp_t *spp,
2515 2520      int *diagnostic, queue_t *pfkey_q)
2516 2521  {
2517 2522          sadb_sa_t *assoc = (sadb_sa_t *)ksi->ks_in_extv[SADB_EXT_SA];
2518 2523          struct sadb_purge_state ps;
2519 2524          int error;
2520 2525  
2521 2526          ps.sq.spp = spp;                /* XXX param */
2522 2527  
2523 2528          error = sadb_form_query(ksi, IPSA_Q_DST|IPSA_Q_SRC,
2524 2529              IPSA_Q_SRC|IPSA_Q_DST|IPSA_Q_SRCID|IPSA_Q_DSTID|IPSA_Q_KMC,
2525 2530              &ps.sq, diagnostic);
2526 2531          if (error != 0)
2527 2532                  return (error);
2528 2533  
2529 2534          ps.inbnd = B_FALSE;
2530 2535          ps.sadb_sa_state = assoc->sadb_sa_state;
2531 2536          sadb_walker(ps.sq.sp->sdb_of, ps.sq.sp->sdb_hashsize,
2532 2537              sadb_delpair_state_one, &ps);
2533 2538  
2534 2539          ASSERT(mp->b_cont != NULL);
2535 2540          sadb_pfkey_echo(pfkey_q, mp, (sadb_msg_t *)mp->b_cont->b_rptr,
2536 2541              ksi, NULL);
2537 2542          return (0);
2538 2543  }
2539 2544  
2540 2545  /*
2541 2546   * Common code to delete/get an SA.
2542 2547   */
2543 2548  int
2544 2549  sadb_delget_sa(mblk_t *mp, keysock_in_t *ksi, sadbp_t *spp,
2545 2550      int *diagnostic, queue_t *pfkey_q, uint8_t sadb_msg_type)
2546 2551  {
2547 2552          ipsa_query_t sq;
2548 2553          ipsa_t *echo_target = NULL;
2549 2554          ipsap_t ipsapp;
2550 2555          uint_t  error = 0;
2551 2556  
2552 2557          if (sadb_msg_type == SADB_X_DELPAIR_STATE)
2553 2558                  return (sadb_delpair_state(mp, ksi, spp, diagnostic, pfkey_q));
2554 2559  
2555 2560          sq.spp = spp;           /* XXX param */
2556 2561          error = sadb_form_query(ksi, IPSA_Q_DST|IPSA_Q_SA,
2557 2562              IPSA_Q_SRC|IPSA_Q_DST|IPSA_Q_SA|IPSA_Q_INBOUND|IPSA_Q_OUTBOUND,
2558 2563              &sq, diagnostic);
2559 2564          if (error != 0)
2560 2565                  return (error);
2561 2566  
2562 2567          error = get_ipsa_pair(&sq, &ipsapp, diagnostic);
2563 2568          if (error != 0) {
2564 2569                  return (error);
2565 2570          }
2566 2571  
2567 2572          echo_target = ipsapp.ipsap_sa_ptr;
2568 2573          if (echo_target == NULL)
2569 2574                  echo_target = ipsapp.ipsap_psa_ptr;
2570 2575  
2571 2576          if (sadb_msg_type == SADB_DELETE || sadb_msg_type == SADB_X_DELPAIR) {
2572 2577                  /*
2573 2578                   * Bucket locks will be required if SA is actually unlinked.
2574 2579                   * get_ipsa_pair() returns valid hash bucket pointers even
2575 2580                   * if it can't find a pair SA pointer. To prevent a potential
2576 2581                   * deadlock, always lock the outbound bucket before the inbound.
2577 2582                   */
2578 2583                  if (ipsapp.in_inbound_table) {
2579 2584                          mutex_enter(&ipsapp.ipsap_pbucket->isaf_lock);
2580 2585                          mutex_enter(&ipsapp.ipsap_bucket->isaf_lock);
2581 2586                  } else {
2582 2587                          mutex_enter(&ipsapp.ipsap_bucket->isaf_lock);
2583 2588                          mutex_enter(&ipsapp.ipsap_pbucket->isaf_lock);
2584 2589                  }
2585 2590  
2586 2591                  if (ipsapp.ipsap_sa_ptr != NULL) {
2587 2592                          mutex_enter(&ipsapp.ipsap_sa_ptr->ipsa_lock);
2588 2593                          if (ipsapp.ipsap_sa_ptr->ipsa_flags & IPSA_F_INBOUND) {
2589 2594                                  sadb_delete_cluster(ipsapp.ipsap_sa_ptr);
2590 2595                          }
2591 2596                          ipsapp.ipsap_sa_ptr->ipsa_state = IPSA_STATE_DEAD;
2592 2597                          (void) sadb_torch_assoc(ipsapp.ipsap_bucket,
2593 2598                              ipsapp.ipsap_sa_ptr);
2594 2599                          /*
2595 2600                           * sadb_torch_assoc() releases the ipsa_lock
2596 2601                           * and calls sadb_unlinkassoc() which does a
2597 2602                           * IPSA_REFRELE.
2598 2603                           */
2599 2604                  }
2600 2605                  if (ipsapp.ipsap_psa_ptr != NULL) {
2601 2606                          mutex_enter(&ipsapp.ipsap_psa_ptr->ipsa_lock);
2602 2607                          if (sadb_msg_type == SADB_X_DELPAIR ||
2603 2608                              ipsapp.ipsap_psa_ptr->ipsa_haspeer) {
2604 2609                                  if (ipsapp.ipsap_psa_ptr->ipsa_flags &
2605 2610                                      IPSA_F_INBOUND) {
2606 2611                                          sadb_delete_cluster
2607 2612                                              (ipsapp.ipsap_psa_ptr);
2608 2613                                  }
2609 2614                                  ipsapp.ipsap_psa_ptr->ipsa_state =
2610 2615                                      IPSA_STATE_DEAD;
2611 2616                                  (void) sadb_torch_assoc(ipsapp.ipsap_pbucket,
2612 2617                                      ipsapp.ipsap_psa_ptr);
2613 2618                          } else {
2614 2619                                  /*
2615 2620                                   * Only half of the "pair" has been deleted.
2616 2621                                   * Update the remaining SA and remove references
2617 2622                                   * to its pair SA, which is now gone.
2618 2623                                   */
2619 2624                                  ipsapp.ipsap_psa_ptr->ipsa_otherspi = 0;
2620 2625                                  ipsapp.ipsap_psa_ptr->ipsa_flags &=
2621 2626                                      ~IPSA_F_PAIRED;
2622 2627                                  mutex_exit(&ipsapp.ipsap_psa_ptr->ipsa_lock);
2623 2628                          }
2624 2629                  } else if (sadb_msg_type == SADB_X_DELPAIR) {
2625 2630                          *diagnostic = SADB_X_DIAGNOSTIC_PAIR_SA_NOTFOUND;
2626 2631                          error = ESRCH;
2627 2632                  }
2628 2633                  mutex_exit(&ipsapp.ipsap_bucket->isaf_lock);
2629 2634                  mutex_exit(&ipsapp.ipsap_pbucket->isaf_lock);
2630 2635          }
2631 2636  
2632 2637          ASSERT(mp->b_cont != NULL);
2633 2638  
2634 2639          if (error == 0)
2635 2640                  sadb_pfkey_echo(pfkey_q, mp, (sadb_msg_t *)
2636 2641                      mp->b_cont->b_rptr, ksi, echo_target);
2637 2642  
2638 2643          destroy_ipsa_pair(&ipsapp);
2639 2644  
2640 2645          return (error);
2641 2646  }
2642 2647  
2643 2648  /*
2644 2649   * This function takes a sadb_sa_t and finds the ipsa_t structure
2645 2650   * and the isaf_t (hash bucket) that its stored under. If the security
2646 2651   * association has a peer, the ipsa_t structure and bucket for that security
2647 2652   * association are also searched for. The "pair" of ipsa_t's and isaf_t's
2648 2653   * are returned as a ipsap_t.
2649 2654   *
2650 2655   * The hash buckets are returned for convenience, if the calling function
2651 2656   * needs to use the hash bucket locks, say to remove the SA's, it should
2652 2657   * take care to observe the convention of locking outbound bucket then
2653 2658   * inbound bucket. The flag in_inbound_table provides direction.
2654 2659   *
2655 2660   * Note that a "pair" is defined as one (but not both) of the following:
2656 2661   *
2657 2662   * A security association which has a soft reference to another security
2658 2663   * association via its SPI.
2659 2664   *
2660 2665   * A security association that is not obviously "inbound" or "outbound" so
2661 2666   * it appears in both hash tables, the "peer" being the same security
2662 2667   * association in the other hash table.
2663 2668   *
2664 2669   * This function will return NULL if the ipsa_t can't be found in the
2665 2670   * inbound or outbound  hash tables (not found). If only one ipsa_t is
2666 2671   * found, the pair ipsa_t will be NULL. Both isaf_t values are valid
2667 2672   * provided at least one ipsa_t is found.
2668 2673   */
2669 2674  static int
2670 2675  get_ipsa_pair(ipsa_query_t *sq, ipsap_t *ipsapp, int *diagnostic)
2671 2676  {
2672 2677          uint32_t pair_srcaddr[IPSA_MAX_ADDRLEN];
2673 2678          uint32_t pair_dstaddr[IPSA_MAX_ADDRLEN];
2674 2679          uint32_t pair_spi;
2675 2680  
2676 2681          init_ipsa_pair(ipsapp);
2677 2682  
2678 2683          ipsapp->in_inbound_table = B_FALSE;
2679 2684  
2680 2685          /* Lock down both buckets. */
2681 2686          mutex_enter(&sq->outbound->isaf_lock);
2682 2687          mutex_enter(&sq->inbound->isaf_lock);
2683 2688  
2684 2689          if (sq->assoc->sadb_sa_flags & IPSA_F_INBOUND) {
2685 2690                  ipsapp->ipsap_sa_ptr = ipsec_getassocbyspi(sq->inbound,
2686 2691                      sq->assoc->sadb_sa_spi, sq->srcaddr, sq->dstaddr, sq->af);
2687 2692                  if (ipsapp->ipsap_sa_ptr != NULL) {
2688 2693                          ipsapp->ipsap_bucket = sq->inbound;
2689 2694                          ipsapp->ipsap_pbucket = sq->outbound;
2690 2695                          ipsapp->in_inbound_table = B_TRUE;
2691 2696                  } else {
2692 2697                          ipsapp->ipsap_sa_ptr = ipsec_getassocbyspi(sq->outbound,
2693 2698                              sq->assoc->sadb_sa_spi, sq->srcaddr, sq->dstaddr,
2694 2699                              sq->af);
2695 2700                          ipsapp->ipsap_bucket = sq->outbound;
2696 2701                          ipsapp->ipsap_pbucket = sq->inbound;
2697 2702                  }
2698 2703          } else {
2699 2704                  /* IPSA_F_OUTBOUND is set *or* no directions flags set. */
2700 2705                  ipsapp->ipsap_sa_ptr =
2701 2706                      ipsec_getassocbyspi(sq->outbound,
2702 2707                      sq->assoc->sadb_sa_spi, sq->srcaddr, sq->dstaddr, sq->af);
2703 2708                  if (ipsapp->ipsap_sa_ptr != NULL) {
2704 2709                          ipsapp->ipsap_bucket = sq->outbound;
2705 2710                          ipsapp->ipsap_pbucket = sq->inbound;
2706 2711                  } else {
2707 2712                          ipsapp->ipsap_sa_ptr = ipsec_getassocbyspi(sq->inbound,
2708 2713                              sq->assoc->sadb_sa_spi, sq->srcaddr, sq->dstaddr,
2709 2714                              sq->af);
2710 2715                          ipsapp->ipsap_bucket = sq->inbound;
2711 2716                          ipsapp->ipsap_pbucket = sq->outbound;
2712 2717                          if (ipsapp->ipsap_sa_ptr != NULL)
2713 2718                                  ipsapp->in_inbound_table = B_TRUE;
2714 2719                  }
2715 2720          }
2716 2721  
2717 2722          if (ipsapp->ipsap_sa_ptr == NULL) {
2718 2723                  mutex_exit(&sq->outbound->isaf_lock);
2719 2724                  mutex_exit(&sq->inbound->isaf_lock);
2720 2725                  *diagnostic = SADB_X_DIAGNOSTIC_SA_NOTFOUND;
2721 2726                  return (ESRCH);
2722 2727          }
2723 2728  
2724 2729          if ((ipsapp->ipsap_sa_ptr->ipsa_state == IPSA_STATE_LARVAL) &&
2725 2730              ipsapp->in_inbound_table) {
2726 2731                  mutex_exit(&sq->outbound->isaf_lock);
2727 2732                  mutex_exit(&sq->inbound->isaf_lock);
2728 2733                  return (0);
2729 2734          }
2730 2735  
2731 2736          mutex_enter(&ipsapp->ipsap_sa_ptr->ipsa_lock);
2732 2737          if (ipsapp->ipsap_sa_ptr->ipsa_haspeer) {
2733 2738                  /*
2734 2739                   * haspeer implies no sa_pairing, look for same spi
2735 2740                   * in other hashtable.
2736 2741                   */
2737 2742                  ipsapp->ipsap_psa_ptr =
2738 2743                      ipsec_getassocbyspi(ipsapp->ipsap_pbucket,
2739 2744                      sq->assoc->sadb_sa_spi, sq->srcaddr, sq->dstaddr, sq->af);
2740 2745                  mutex_exit(&ipsapp->ipsap_sa_ptr->ipsa_lock);
2741 2746                  mutex_exit(&sq->outbound->isaf_lock);
2742 2747                  mutex_exit(&sq->inbound->isaf_lock);
2743 2748                  return (0);
2744 2749          }
2745 2750          pair_spi = ipsapp->ipsap_sa_ptr->ipsa_otherspi;
2746 2751          IPSA_COPY_ADDR(&pair_srcaddr,
2747 2752              ipsapp->ipsap_sa_ptr->ipsa_srcaddr, sq->af);
2748 2753          IPSA_COPY_ADDR(&pair_dstaddr,
2749 2754              ipsapp->ipsap_sa_ptr->ipsa_dstaddr, sq->af);
2750 2755          mutex_exit(&ipsapp->ipsap_sa_ptr->ipsa_lock);
2751 2756          mutex_exit(&sq->inbound->isaf_lock);
2752 2757          mutex_exit(&sq->outbound->isaf_lock);
2753 2758  
2754 2759          if (pair_spi == 0) {
2755 2760                  ASSERT(ipsapp->ipsap_bucket != NULL);
2756 2761                  ASSERT(ipsapp->ipsap_pbucket != NULL);
2757 2762                  return (0);
2758 2763          }
2759 2764  
2760 2765          /* found sa in outbound sadb, peer should be inbound */
2761 2766  
2762 2767          if (ipsapp->in_inbound_table) {
2763 2768                  /* Found SA in inbound table, pair will be in outbound. */
2764 2769                  if (sq->af == AF_INET6) {
2765 2770                          ipsapp->ipsap_pbucket = OUTBOUND_BUCKET_V6(sq->sp,
2766 2771                              *(uint32_t *)pair_srcaddr);
2767 2772                  } else {
2768 2773                          ipsapp->ipsap_pbucket = OUTBOUND_BUCKET_V4(sq->sp,
2769 2774                              *(uint32_t *)pair_srcaddr);
2770 2775                  }
2771 2776          } else {
2772 2777                  ipsapp->ipsap_pbucket = INBOUND_BUCKET(sq->sp, pair_spi);
2773 2778          }
2774 2779          mutex_enter(&ipsapp->ipsap_pbucket->isaf_lock);
2775 2780          ipsapp->ipsap_psa_ptr = ipsec_getassocbyspi(ipsapp->ipsap_pbucket,
2776 2781              pair_spi, pair_dstaddr, pair_srcaddr, sq->af);
2777 2782          mutex_exit(&ipsapp->ipsap_pbucket->isaf_lock);
2778 2783          ASSERT(ipsapp->ipsap_bucket != NULL);
2779 2784          ASSERT(ipsapp->ipsap_pbucket != NULL);
2780 2785          return (0);
2781 2786  }
2782 2787  
2783 2788  /*
2784 2789   * Perform NAT-traversal cached checksum offset calculations here.
2785 2790   */
2786 2791  static void
2787 2792  sadb_nat_calculations(ipsa_t *newbie, sadb_address_t *natt_loc_ext,
2788 2793      sadb_address_t *natt_rem_ext, uint32_t *src_addr_ptr,
2789 2794      uint32_t *dst_addr_ptr)
2790 2795  {
2791 2796          struct sockaddr_in *natt_loc, *natt_rem;
2792 2797          uint32_t *natt_loc_ptr = NULL, *natt_rem_ptr = NULL;
2793 2798          uint32_t running_sum = 0;
2794 2799  
2795 2800  #define DOWN_SUM(x) (x) = ((x) & 0xFFFF) +       ((x) >> 16)
2796 2801  
2797 2802          if (natt_rem_ext != NULL) {
2798 2803                  uint32_t l_src;
2799 2804                  uint32_t l_rem;
2800 2805  
2801 2806                  natt_rem = (struct sockaddr_in *)(natt_rem_ext + 1);
2802 2807  
2803 2808                  /* Ensured by sadb_addrfix(). */
2804 2809                  ASSERT(natt_rem->sin_family == AF_INET);
2805 2810  
2806 2811                  natt_rem_ptr = (uint32_t *)(&natt_rem->sin_addr);
2807 2812                  newbie->ipsa_remote_nat_port = natt_rem->sin_port;
2808 2813                  l_src = *src_addr_ptr;
2809 2814                  l_rem = *natt_rem_ptr;
2810 2815  
2811 2816                  /* Instead of IPSA_COPY_ADDR(), just copy first 32 bits. */
2812 2817                  newbie->ipsa_natt_addr_rem = *natt_rem_ptr;
2813 2818  
2814 2819                  l_src = ntohl(l_src);
2815 2820                  DOWN_SUM(l_src);
2816 2821                  DOWN_SUM(l_src);
2817 2822                  l_rem = ntohl(l_rem);
2818 2823                  DOWN_SUM(l_rem);
2819 2824                  DOWN_SUM(l_rem);
2820 2825  
2821 2826                  /*
2822 2827                   * We're 1's complement for checksums, so check for wraparound
2823 2828                   * here.
2824 2829                   */
2825 2830                  if (l_rem > l_src)
2826 2831                          l_src--;
2827 2832  
2828 2833                  running_sum += l_src - l_rem;
2829 2834  
2830 2835                  DOWN_SUM(running_sum);
2831 2836                  DOWN_SUM(running_sum);
2832 2837          }
2833 2838  
2834 2839          if (natt_loc_ext != NULL) {
2835 2840                  natt_loc = (struct sockaddr_in *)(natt_loc_ext + 1);
2836 2841  
2837 2842                  /* Ensured by sadb_addrfix(). */
2838 2843                  ASSERT(natt_loc->sin_family == AF_INET);
2839 2844  
2840 2845                  natt_loc_ptr = (uint32_t *)(&natt_loc->sin_addr);
2841 2846                  newbie->ipsa_local_nat_port = natt_loc->sin_port;
2842 2847  
2843 2848                  /* Instead of IPSA_COPY_ADDR(), just copy first 32 bits. */
2844 2849                  newbie->ipsa_natt_addr_loc = *natt_loc_ptr;
2845 2850  
2846 2851                  /*
2847 2852                   * NAT-T port agility means we may have natt_loc_ext, but
2848 2853                   * only for a local-port change.
2849 2854                   */
2850 2855                  if (natt_loc->sin_addr.s_addr != INADDR_ANY) {
2851 2856                          uint32_t l_dst = ntohl(*dst_addr_ptr);
2852 2857                          uint32_t l_loc = ntohl(*natt_loc_ptr);
2853 2858  
2854 2859                          DOWN_SUM(l_loc);
2855 2860                          DOWN_SUM(l_loc);
2856 2861                          DOWN_SUM(l_dst);
2857 2862                          DOWN_SUM(l_dst);
2858 2863  
2859 2864                          /*
2860 2865                           * We're 1's complement for checksums, so check for
2861 2866                           * wraparound here.
2862 2867                           */
2863 2868                          if (l_loc > l_dst)
2864 2869                                  l_dst--;
2865 2870  
2866 2871                          running_sum += l_dst - l_loc;
2867 2872                          DOWN_SUM(running_sum);
2868 2873                          DOWN_SUM(running_sum);
2869 2874                  }
2870 2875          }
2871 2876  
2872 2877          newbie->ipsa_inbound_cksum = running_sum;
2873 2878  #undef DOWN_SUM
2874 2879  }
2875 2880  
2876 2881  /*
2877 2882   * This function is called from consumers that need to insert a fully-grown
2878 2883   * security association into its tables.  This function takes into account that
2879 2884   * SAs can be "inbound", "outbound", or "both".  The "primary" and "secondary"
2880 2885   * hash bucket parameters are set in order of what the SA will be most of the
2881 2886   * time.  (For example, an SA with an unspecified source, and a multicast
2882 2887   * destination will primarily be an outbound SA.  OTOH, if that destination
2883 2888   * is unicast for this node, then the SA will primarily be inbound.)
2884 2889   *
2885 2890   * It takes a lot of parameters because even if clone is B_FALSE, this needs
2886 2891   * to check both buckets for purposes of collision.
2887 2892   *
2888 2893   * Return 0 upon success.  Return various errnos (ENOMEM, EEXIST) for
2889 2894   * various error conditions.  We may need to set samsg->sadb_x_msg_diagnostic
2890 2895   * with additional diagnostic information because there is at least one EINVAL
2891 2896   * case here.
2892 2897   */
2893 2898  int
2894 2899  sadb_common_add(queue_t *pfkey_q, mblk_t *mp, sadb_msg_t *samsg,
2895 2900      keysock_in_t *ksi, isaf_t *primary, isaf_t *secondary,
2896 2901      ipsa_t *newbie, boolean_t clone, boolean_t is_inbound, int *diagnostic,
2897 2902      netstack_t *ns, sadbp_t *spp)
2898 2903  {
2899 2904          ipsa_t *newbie_clone = NULL, *scratch;
2900 2905          ipsap_t ipsapp;
2901 2906          sadb_sa_t *assoc = (sadb_sa_t *)ksi->ks_in_extv[SADB_EXT_SA];
2902 2907          sadb_address_t *srcext =
2903 2908              (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_SRC];
2904 2909          sadb_address_t *dstext =
2905 2910              (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_DST];
2906 2911          sadb_address_t *isrcext =
2907 2912              (sadb_address_t *)ksi->ks_in_extv[SADB_X_EXT_ADDRESS_INNER_SRC];
2908 2913          sadb_address_t *idstext =
2909 2914              (sadb_address_t *)ksi->ks_in_extv[SADB_X_EXT_ADDRESS_INNER_DST];
2910 2915          sadb_x_kmc_t *kmcext =
2911 2916              (sadb_x_kmc_t *)ksi->ks_in_extv[SADB_X_EXT_KM_COOKIE];
2912 2917          sadb_key_t *akey = (sadb_key_t *)ksi->ks_in_extv[SADB_EXT_KEY_AUTH];
2913 2918          sadb_key_t *ekey = (sadb_key_t *)ksi->ks_in_extv[SADB_EXT_KEY_ENCRYPT];
2914 2919          sadb_sens_t *sens =
2915 2920              (sadb_sens_t *)ksi->ks_in_extv[SADB_EXT_SENSITIVITY];
2916 2921          sadb_sens_t *osens =
2917 2922              (sadb_sens_t *)ksi->ks_in_extv[SADB_X_EXT_OUTER_SENS];
2918 2923          sadb_x_pair_t *pair_ext =
2919 2924              (sadb_x_pair_t *)ksi->ks_in_extv[SADB_X_EXT_PAIR];
2920 2925          sadb_x_replay_ctr_t *replayext =
2921 2926              (sadb_x_replay_ctr_t *)ksi->ks_in_extv[SADB_X_EXT_REPLAY_VALUE];
2922 2927          uint8_t protocol =
2923 2928              (samsg->sadb_msg_satype == SADB_SATYPE_AH) ? IPPROTO_AH:IPPROTO_ESP;
2924 2929          int salt_offset;
2925 2930          uint8_t *buf_ptr;
2926 2931          struct sockaddr_in *src, *dst, *isrc, *idst;
2927 2932          struct sockaddr_in6 *src6, *dst6, *isrc6, *idst6;
2928 2933          sadb_lifetime_t *soft =
2929 2934              (sadb_lifetime_t *)ksi->ks_in_extv[SADB_EXT_LIFETIME_SOFT];
2930 2935          sadb_lifetime_t *hard =
2931 2936              (sadb_lifetime_t *)ksi->ks_in_extv[SADB_EXT_LIFETIME_HARD];
2932 2937          sadb_lifetime_t *idle =
2933 2938              (sadb_lifetime_t *)ksi->ks_in_extv[SADB_X_EXT_LIFETIME_IDLE];
2934 2939          sa_family_t af;
2935 2940          int error = 0;
2936 2941          boolean_t isupdate = (newbie != NULL);
2937 2942          uint32_t *src_addr_ptr, *dst_addr_ptr, *isrc_addr_ptr, *idst_addr_ptr;
2938 2943          ipsec_stack_t   *ipss = ns->netstack_ipsec;
2939 2944          ip_stack_t      *ipst = ns->netstack_ip;
2940 2945          ipsec_alginfo_t *alg;
2941 2946          int             rcode;
2942 2947          boolean_t       async = B_FALSE;
2943 2948  
2944 2949          init_ipsa_pair(&ipsapp);
2945 2950  
2946 2951          if (srcext == NULL) {
2947 2952                  *diagnostic = SADB_X_DIAGNOSTIC_MISSING_SRC;
2948 2953                  return (EINVAL);
2949 2954          }
2950 2955          if (dstext == NULL) {
2951 2956                  *diagnostic = SADB_X_DIAGNOSTIC_MISSING_DST;
2952 2957                  return (EINVAL);
2953 2958          }
2954 2959          if (assoc == NULL) {
2955 2960                  *diagnostic = SADB_X_DIAGNOSTIC_MISSING_SA;
2956 2961                  return (EINVAL);
2957 2962          }
2958 2963  
2959 2964          src = (struct sockaddr_in *)(srcext + 1);
2960 2965          src6 = (struct sockaddr_in6 *)(srcext + 1);
2961 2966          dst = (struct sockaddr_in *)(dstext + 1);
2962 2967          dst6 = (struct sockaddr_in6 *)(dstext + 1);
2963 2968          if (isrcext != NULL) {
2964 2969                  isrc = (struct sockaddr_in *)(isrcext + 1);
2965 2970                  isrc6 = (struct sockaddr_in6 *)(isrcext + 1);
2966 2971                  ASSERT(idstext != NULL);
2967 2972                  idst = (struct sockaddr_in *)(idstext + 1);
2968 2973                  idst6 = (struct sockaddr_in6 *)(idstext + 1);
2969 2974          } else {
2970 2975                  isrc = NULL;
2971 2976                  isrc6 = NULL;
2972 2977          }
2973 2978  
2974 2979          af = src->sin_family;
2975 2980  
2976 2981          if (af == AF_INET) {
2977 2982                  src_addr_ptr = (uint32_t *)&src->sin_addr;
2978 2983                  dst_addr_ptr = (uint32_t *)&dst->sin_addr;
2979 2984          } else {
2980 2985                  ASSERT(af == AF_INET6);
2981 2986                  src_addr_ptr = (uint32_t *)&src6->sin6_addr;
2982 2987                  dst_addr_ptr = (uint32_t *)&dst6->sin6_addr;
2983 2988          }
2984 2989  
2985 2990          if (!isupdate && (clone == B_TRUE || is_inbound == B_TRUE) &&
2986 2991              cl_inet_checkspi &&
2987 2992              (assoc->sadb_sa_state != SADB_X_SASTATE_ACTIVE_ELSEWHERE)) {
2988 2993                  rcode = cl_inet_checkspi(ns->netstack_stackid, protocol,
2989 2994                      assoc->sadb_sa_spi, NULL);
2990 2995                  if (rcode == -1) {
2991 2996                          return (EEXIST);
2992 2997                  }
2993 2998          }
2994 2999  
2995 3000          /*
2996 3001           * Check to see if the new SA will be cloned AND paired. The
2997 3002           * reason a SA will be cloned is the source or destination addresses
2998 3003           * are not specific enough to determine if the SA goes in the outbound
2999 3004           * or the inbound hash table, so its cloned and put in both. If
3000 3005           * the SA is paired, it's soft linked to another SA for the other
3001 3006           * direction. Keeping track and looking up SA's that are direction
3002 3007           * unspecific and linked is too hard.
3003 3008           */
3004 3009          if (clone && (pair_ext != NULL)) {
3005 3010                  *diagnostic = SADB_X_DIAGNOSTIC_PAIR_INAPPROPRIATE;
3006 3011                  return (EINVAL);
3007 3012          }
3008 3013  
3009 3014          if (!isupdate) {
3010 3015                  newbie = sadb_makelarvalassoc(assoc->sadb_sa_spi,
3011 3016                      src_addr_ptr, dst_addr_ptr, af, ns);
3012 3017                  if (newbie == NULL)
3013 3018                          return (ENOMEM);
3014 3019          }
3015 3020  
3016 3021          mutex_enter(&newbie->ipsa_lock);
3017 3022  
3018 3023          if (isrc != NULL) {
3019 3024                  if (isrc->sin_family == AF_INET) {
3020 3025                          if (srcext->sadb_address_proto != IPPROTO_ENCAP) {
3021 3026                                  if (srcext->sadb_address_proto != 0) {
3022 3027                                          /*
3023 3028                                           * Mismatched outer-packet protocol
3024 3029                                           * and inner-packet address family.
3025 3030                                           */
3026 3031                                          mutex_exit(&newbie->ipsa_lock);
3027 3032                                          error = EPROTOTYPE;
3028 3033                                          *diagnostic =
3029 3034                                              SADB_X_DIAGNOSTIC_INNER_AF_MISMATCH;
3030 3035                                          goto error;
3031 3036                                  } else {
3032 3037                                          /* Fill in with explicit protocol. */
3033 3038                                          srcext->sadb_address_proto =
3034 3039                                              IPPROTO_ENCAP;
3035 3040                                          dstext->sadb_address_proto =
3036 3041                                              IPPROTO_ENCAP;
3037 3042                                  }
3038 3043                          }
3039 3044                          isrc_addr_ptr = (uint32_t *)&isrc->sin_addr;
3040 3045                          idst_addr_ptr = (uint32_t *)&idst->sin_addr;
3041 3046                  } else {
3042 3047                          ASSERT(isrc->sin_family == AF_INET6);
3043 3048                          if (srcext->sadb_address_proto != IPPROTO_IPV6) {
3044 3049                                  if (srcext->sadb_address_proto != 0) {
3045 3050                                          /*
3046 3051                                           * Mismatched outer-packet protocol
3047 3052                                           * and inner-packet address family.
3048 3053                                           */
3049 3054                                          mutex_exit(&newbie->ipsa_lock);
3050 3055                                          error = EPROTOTYPE;
3051 3056                                          *diagnostic =
3052 3057                                              SADB_X_DIAGNOSTIC_INNER_AF_MISMATCH;
3053 3058                                          goto error;
3054 3059                                  } else {
3055 3060                                          /* Fill in with explicit protocol. */
3056 3061                                          srcext->sadb_address_proto =
3057 3062                                              IPPROTO_IPV6;
3058 3063                                          dstext->sadb_address_proto =
3059 3064                                              IPPROTO_IPV6;
3060 3065                                  }
3061 3066                          }
3062 3067                          isrc_addr_ptr = (uint32_t *)&isrc6->sin6_addr;
3063 3068                          idst_addr_ptr = (uint32_t *)&idst6->sin6_addr;
3064 3069                  }
3065 3070                  newbie->ipsa_innerfam = isrc->sin_family;
3066 3071  
3067 3072                  IPSA_COPY_ADDR(newbie->ipsa_innersrc, isrc_addr_ptr,
3068 3073                      newbie->ipsa_innerfam);
3069 3074                  IPSA_COPY_ADDR(newbie->ipsa_innerdst, idst_addr_ptr,
3070 3075                      newbie->ipsa_innerfam);
3071 3076                  newbie->ipsa_innersrcpfx = isrcext->sadb_address_prefixlen;
3072 3077                  newbie->ipsa_innerdstpfx = idstext->sadb_address_prefixlen;
3073 3078  
3074 3079                  /* Unique value uses inner-ports for Tunnel Mode... */
3075 3080                  newbie->ipsa_unique_id = SA_UNIQUE_ID(isrc->sin_port,
3076 3081                      idst->sin_port, dstext->sadb_address_proto,
3077 3082                      idstext->sadb_address_proto);
3078 3083                  newbie->ipsa_unique_mask = SA_UNIQUE_MASK(isrc->sin_port,
3079 3084                      idst->sin_port, dstext->sadb_address_proto,
3080 3085                      idstext->sadb_address_proto);
3081 3086          } else {
3082 3087                  /* ... and outer-ports for Transport Mode. */
3083 3088                  newbie->ipsa_unique_id = SA_UNIQUE_ID(src->sin_port,
3084 3089                      dst->sin_port, dstext->sadb_address_proto, 0);
3085 3090                  newbie->ipsa_unique_mask = SA_UNIQUE_MASK(src->sin_port,
3086 3091                      dst->sin_port, dstext->sadb_address_proto, 0);
3087 3092          }
3088 3093          if (newbie->ipsa_unique_mask != (uint64_t)0)
3089 3094                  newbie->ipsa_flags |= IPSA_F_UNIQUE;
3090 3095  
3091 3096          sadb_nat_calculations(newbie,
3092 3097              (sadb_address_t *)ksi->ks_in_extv[SADB_X_EXT_ADDRESS_NATT_LOC],
3093 3098              (sadb_address_t *)ksi->ks_in_extv[SADB_X_EXT_ADDRESS_NATT_REM],
3094 3099              src_addr_ptr, dst_addr_ptr);
3095 3100  
3096 3101          newbie->ipsa_type = samsg->sadb_msg_satype;
3097 3102  
3098 3103          ASSERT((assoc->sadb_sa_state == SADB_SASTATE_MATURE) ||
3099 3104              (assoc->sadb_sa_state == SADB_X_SASTATE_ACTIVE_ELSEWHERE));
3100 3105          newbie->ipsa_auth_alg = assoc->sadb_sa_auth;
3101 3106          newbie->ipsa_encr_alg = assoc->sadb_sa_encrypt;
3102 3107  
3103 3108          newbie->ipsa_flags |= assoc->sadb_sa_flags;
3104 3109          if (newbie->ipsa_flags & SADB_X_SAFLAGS_NATT_LOC &&
3105 3110              ksi->ks_in_extv[SADB_X_EXT_ADDRESS_NATT_LOC] == NULL) {
3106 3111                  mutex_exit(&newbie->ipsa_lock);
3107 3112                  *diagnostic = SADB_X_DIAGNOSTIC_MISSING_NATT_LOC;
3108 3113                  error = EINVAL;
3109 3114                  goto error;
3110 3115          }
3111 3116          if (newbie->ipsa_flags & SADB_X_SAFLAGS_NATT_REM &&
3112 3117              ksi->ks_in_extv[SADB_X_EXT_ADDRESS_NATT_REM] == NULL) {
3113 3118                  mutex_exit(&newbie->ipsa_lock);
3114 3119                  *diagnostic = SADB_X_DIAGNOSTIC_MISSING_NATT_REM;
3115 3120                  error = EINVAL;
3116 3121                  goto error;
3117 3122          }
3118 3123          if (newbie->ipsa_flags & SADB_X_SAFLAGS_TUNNEL &&
3119 3124              ksi->ks_in_extv[SADB_X_EXT_ADDRESS_INNER_SRC] == NULL) {
3120 3125                  mutex_exit(&newbie->ipsa_lock);
3121 3126                  *diagnostic = SADB_X_DIAGNOSTIC_MISSING_INNER_SRC;
3122 3127                  error = EINVAL;
3123 3128                  goto error;
3124 3129          }
3125 3130          /*
3126 3131           * If unspecified source address, force replay_wsize to 0.
3127 3132           * This is because an SA that has multiple sources of secure
3128 3133           * traffic cannot enforce a replay counter w/o synchronizing the
3129 3134           * senders.
  
    | 
      ↓ open down ↓ | 
    786 lines elided | 
    
      ↑ open up ↑ | 
  
3130 3135           */
3131 3136          if (ksi->ks_in_srctype != KS_IN_ADDR_UNSPEC)
3132 3137                  newbie->ipsa_replay_wsize = assoc->sadb_sa_replay;
3133 3138          else
3134 3139                  newbie->ipsa_replay_wsize = 0;
3135 3140  
3136 3141          newbie->ipsa_addtime = gethrestime_sec();
3137 3142  
3138 3143          if (kmcext != NULL) {
3139 3144                  newbie->ipsa_kmp = kmcext->sadb_x_kmc_proto;
3140      -                /* Be liberal in what we receive.  Special-case IKEv1. */
     3145 +                /*
     3146 +                 * Be liberal in what we receive.  Special-case the IKEv1
     3147 +                 * cookie, which closed-source in.iked assumes is 32 bits.
     3148 +                 * Now that we store all 64 bits, we should pre-zero the
     3149 +                 * reserved field on behalf of closed-source in.iked.
     3150 +                 */
3141 3151                  if (newbie->ipsa_kmp == SADB_X_KMP_IKE) {
3142 3152                          /* Just in case in.iked is misbehaving... */
3143 3153                          kmcext->sadb_x_kmc_reserved = 0;
3144 3154                  }
3145 3155                  newbie->ipsa_kmc = kmcext->sadb_x_kmc_cookie64;
3146 3156          }
3147 3157  
3148 3158          /*
3149 3159           * XXX CURRENT lifetime checks MAY BE needed for an UPDATE.
3150 3160           * The spec says that one can update current lifetimes, but
3151 3161           * that seems impractical, especially in the larval-to-mature
3152 3162           * update that this function performs.
3153 3163           */
3154 3164          if (soft != NULL) {
3155 3165                  newbie->ipsa_softaddlt = soft->sadb_lifetime_addtime;
3156 3166                  newbie->ipsa_softuselt = soft->sadb_lifetime_usetime;
3157 3167                  newbie->ipsa_softbyteslt = soft->sadb_lifetime_bytes;
3158 3168                  newbie->ipsa_softalloc = soft->sadb_lifetime_allocations;
3159 3169                  SET_EXPIRE(newbie, softaddlt, softexpiretime);
3160 3170          }
3161 3171          if (hard != NULL) {
3162 3172                  newbie->ipsa_hardaddlt = hard->sadb_lifetime_addtime;
3163 3173                  newbie->ipsa_harduselt = hard->sadb_lifetime_usetime;
3164 3174                  newbie->ipsa_hardbyteslt = hard->sadb_lifetime_bytes;
3165 3175                  newbie->ipsa_hardalloc = hard->sadb_lifetime_allocations;
3166 3176                  SET_EXPIRE(newbie, hardaddlt, hardexpiretime);
3167 3177          }
3168 3178          if (idle != NULL) {
3169 3179                  newbie->ipsa_idleaddlt = idle->sadb_lifetime_addtime;
3170 3180                  newbie->ipsa_idleuselt = idle->sadb_lifetime_usetime;
3171 3181                  newbie->ipsa_idleexpiretime = newbie->ipsa_addtime +
3172 3182                      newbie->ipsa_idleaddlt;
3173 3183                  newbie->ipsa_idletime = newbie->ipsa_idleaddlt;
3174 3184          }
3175 3185  
3176 3186          newbie->ipsa_authtmpl = NULL;
3177 3187          newbie->ipsa_encrtmpl = NULL;
3178 3188  
3179 3189  #ifdef IPSEC_LATENCY_TEST
3180 3190          if (akey != NULL && newbie->ipsa_auth_alg != SADB_AALG_NONE) {
3181 3191  #else
3182 3192          if (akey != NULL) {
3183 3193  #endif
3184 3194                  async = (ipss->ipsec_algs_exec_mode[IPSEC_ALG_AUTH] ==
3185 3195                      IPSEC_ALGS_EXEC_ASYNC);
3186 3196  
3187 3197                  newbie->ipsa_authkeybits = akey->sadb_key_bits;
3188 3198                  newbie->ipsa_authkeylen = SADB_1TO8(akey->sadb_key_bits);
3189 3199                  /* In case we have to round up to the next byte... */
3190 3200                  if ((akey->sadb_key_bits & 0x7) != 0)
3191 3201                          newbie->ipsa_authkeylen++;
3192 3202                  newbie->ipsa_authkey = kmem_alloc(newbie->ipsa_authkeylen,
3193 3203                      KM_NOSLEEP);
3194 3204                  if (newbie->ipsa_authkey == NULL) {
3195 3205                          error = ENOMEM;
3196 3206                          mutex_exit(&newbie->ipsa_lock);
3197 3207                          goto error;
3198 3208                  }
3199 3209                  bcopy(akey + 1, newbie->ipsa_authkey, newbie->ipsa_authkeylen);
3200 3210                  bzero(akey + 1, newbie->ipsa_authkeylen);
3201 3211  
3202 3212                  /*
3203 3213                   * Pre-initialize the kernel crypto framework key
3204 3214                   * structure.
3205 3215                   */
3206 3216                  newbie->ipsa_kcfauthkey.ck_format = CRYPTO_KEY_RAW;
3207 3217                  newbie->ipsa_kcfauthkey.ck_length = newbie->ipsa_authkeybits;
3208 3218                  newbie->ipsa_kcfauthkey.ck_data = newbie->ipsa_authkey;
3209 3219  
3210 3220                  rw_enter(&ipss->ipsec_alg_lock, RW_READER);
3211 3221                  alg = ipss->ipsec_alglists[IPSEC_ALG_AUTH]
3212 3222                      [newbie->ipsa_auth_alg];
3213 3223                  if (alg != NULL && ALG_VALID(alg)) {
3214 3224                          newbie->ipsa_amech.cm_type = alg->alg_mech_type;
3215 3225                          newbie->ipsa_amech.cm_param =
3216 3226                              (char *)&newbie->ipsa_mac_len;
3217 3227                          newbie->ipsa_amech.cm_param_len = sizeof (size_t);
3218 3228                          newbie->ipsa_mac_len = (size_t)alg->alg_datalen;
3219 3229                  } else {
3220 3230                          newbie->ipsa_amech.cm_type = CRYPTO_MECHANISM_INVALID;
3221 3231                  }
3222 3232                  error = ipsec_create_ctx_tmpl(newbie, IPSEC_ALG_AUTH);
3223 3233                  rw_exit(&ipss->ipsec_alg_lock);
3224 3234                  if (error != 0) {
3225 3235                          mutex_exit(&newbie->ipsa_lock);
3226 3236                          /*
3227 3237                           * An error here indicates that alg is the wrong type
3228 3238                           * (IE: not authentication) or its not in the alg tables
3229 3239                           * created by ipsecalgs(1m), or Kcf does not like the
3230 3240                           * parameters passed in with this algorithm, which is
3231 3241                           * probably a coding error!
3232 3242                           */
3233 3243                          *diagnostic = SADB_X_DIAGNOSTIC_BAD_CTX;
3234 3244  
3235 3245                          goto error;
3236 3246                  }
3237 3247          }
3238 3248  
3239 3249          if (ekey != NULL) {
3240 3250                  rw_enter(&ipss->ipsec_alg_lock, RW_READER);
3241 3251                  async = async || (ipss->ipsec_algs_exec_mode[IPSEC_ALG_ENCR] ==
3242 3252                      IPSEC_ALGS_EXEC_ASYNC);
3243 3253                  alg = ipss->ipsec_alglists[IPSEC_ALG_ENCR]
3244 3254                      [newbie->ipsa_encr_alg];
3245 3255  
3246 3256                  if (alg != NULL && ALG_VALID(alg)) {
3247 3257                          newbie->ipsa_emech.cm_type = alg->alg_mech_type;
3248 3258                          newbie->ipsa_datalen = alg->alg_datalen;
3249 3259                          if (alg->alg_flags & ALG_FLAG_COUNTERMODE)
3250 3260                                  newbie->ipsa_flags |= IPSA_F_COUNTERMODE;
3251 3261  
3252 3262                          if (alg->alg_flags & ALG_FLAG_COMBINED) {
3253 3263                                  newbie->ipsa_flags |= IPSA_F_COMBINED;
3254 3264                                  newbie->ipsa_mac_len =  alg->alg_icvlen;
3255 3265                          }
3256 3266  
3257 3267                          if (alg->alg_flags & ALG_FLAG_CCM)
3258 3268                                  newbie->ipsa_noncefunc = ccm_params_init;
3259 3269                          else if (alg->alg_flags & ALG_FLAG_GCM)
3260 3270                                  newbie->ipsa_noncefunc = gcm_params_init;
3261 3271                          else newbie->ipsa_noncefunc = cbc_params_init;
3262 3272  
3263 3273                          newbie->ipsa_saltlen = alg->alg_saltlen;
3264 3274                          newbie->ipsa_saltbits = SADB_8TO1(newbie->ipsa_saltlen);
3265 3275                          newbie->ipsa_iv_len = alg->alg_ivlen;
3266 3276                          newbie->ipsa_nonce_len = newbie->ipsa_saltlen +
3267 3277                              newbie->ipsa_iv_len;
3268 3278                          newbie->ipsa_emech.cm_param = NULL;
3269 3279                          newbie->ipsa_emech.cm_param_len = 0;
3270 3280                  } else {
3271 3281                          newbie->ipsa_emech.cm_type = CRYPTO_MECHANISM_INVALID;
3272 3282                  }
3273 3283                  rw_exit(&ipss->ipsec_alg_lock);
3274 3284  
3275 3285                  /*
3276 3286                   * The byte stream following the sadb_key_t is made up of:
3277 3287                   * key bytes, [salt bytes], [IV initial value]
3278 3288                   * All of these have variable length. The IV is typically
3279 3289                   * randomly generated by this function and not passed in.
3280 3290                   * By supporting the injection of a known IV, the whole
3281 3291                   * IPsec subsystem and the underlying crypto subsystem
3282 3292                   * can be tested with known test vectors.
3283 3293                   *
3284 3294                   * The keying material has been checked by ext_check()
3285 3295                   * and ipsec_valid_key_size(), after removing salt/IV
3286 3296                   * bits, whats left is the encryption key. If this is too
3287 3297                   * short, ipsec_create_ctx_tmpl() will fail and the SA
3288 3298                   * won't get created.
3289 3299                   *
3290 3300                   * set ipsa_encrkeylen to length of key only.
3291 3301                   */
3292 3302                  newbie->ipsa_encrkeybits = ekey->sadb_key_bits;
3293 3303                  newbie->ipsa_encrkeybits -= ekey->sadb_key_reserved;
3294 3304                  newbie->ipsa_encrkeybits -= newbie->ipsa_saltbits;
3295 3305                  newbie->ipsa_encrkeylen = SADB_1TO8(newbie->ipsa_encrkeybits);
3296 3306  
3297 3307                  /* In case we have to round up to the next byte... */
3298 3308                  if ((ekey->sadb_key_bits & 0x7) != 0)
3299 3309                          newbie->ipsa_encrkeylen++;
3300 3310  
3301 3311                  newbie->ipsa_encrkey = kmem_alloc(newbie->ipsa_encrkeylen,
3302 3312                      KM_NOSLEEP);
3303 3313                  if (newbie->ipsa_encrkey == NULL) {
3304 3314                          error = ENOMEM;
3305 3315                          mutex_exit(&newbie->ipsa_lock);
3306 3316                          goto error;
3307 3317                  }
3308 3318  
3309 3319                  buf_ptr = (uint8_t *)(ekey + 1);
3310 3320                  bcopy(buf_ptr, newbie->ipsa_encrkey, newbie->ipsa_encrkeylen);
3311 3321  
3312 3322                  if (newbie->ipsa_flags & IPSA_F_COMBINED) {
3313 3323                          /*
3314 3324                           * Combined mode algs need a nonce. Copy the salt and
3315 3325                           * IV into a buffer. The ipsa_nonce is a pointer into
3316 3326                           * this buffer, some bytes at the start of the buffer
3317 3327                           * may be unused, depends on the salt length. The IV
3318 3328                           * is 64 bit aligned so it can be incremented as a
3319 3329                           * uint64_t. Zero out key in samsg_t before freeing.
3320 3330                           */
3321 3331  
3322 3332                          newbie->ipsa_nonce_buf = kmem_alloc(
3323 3333                              sizeof (ipsec_nonce_t), KM_NOSLEEP);
3324 3334                          if (newbie->ipsa_nonce_buf == NULL) {
3325 3335                                  error = ENOMEM;
3326 3336                                  mutex_exit(&newbie->ipsa_lock);
3327 3337                                  goto error;
3328 3338                          }
3329 3339                          /*
3330 3340                           * Initialize nonce and salt pointers to point
3331 3341                           * to the nonce buffer. This is just in case we get
3332 3342                           * bad data, the pointers will be valid, the data
3333 3343                           * won't be.
3334 3344                           *
3335 3345                           * See sadb.h for layout of nonce.
3336 3346                           */
3337 3347                          newbie->ipsa_iv = &newbie->ipsa_nonce_buf->iv;
3338 3348                          newbie->ipsa_salt = (uint8_t *)newbie->ipsa_nonce_buf;
3339 3349                          newbie->ipsa_nonce = newbie->ipsa_salt;
3340 3350                          if (newbie->ipsa_saltlen != 0) {
3341 3351                                  salt_offset = MAXSALTSIZE -
3342 3352                                      newbie->ipsa_saltlen;
3343 3353                                  newbie->ipsa_salt = (uint8_t *)
3344 3354                                      &newbie->ipsa_nonce_buf->salt[salt_offset];
3345 3355                                  newbie->ipsa_nonce = newbie->ipsa_salt;
3346 3356                                  buf_ptr += newbie->ipsa_encrkeylen;
3347 3357                                  bcopy(buf_ptr, newbie->ipsa_salt,
3348 3358                                      newbie->ipsa_saltlen);
3349 3359                          }
3350 3360                          /*
3351 3361                           * The IV for CCM/GCM mode increments, it should not
3352 3362                           * repeat. Get a random value for the IV, make a
3353 3363                           * copy, the SA will expire when/if the IV ever
3354 3364                           * wraps back to the initial value. If an Initial IV
3355 3365                           * is passed in via PF_KEY, save this in the SA.
3356 3366                           * Initialising IV for inbound is pointless as its
3357 3367                           * taken from the inbound packet.
3358 3368                           */
3359 3369                          if (!is_inbound) {
3360 3370                                  if (ekey->sadb_key_reserved != 0) {
3361 3371                                          buf_ptr += newbie->ipsa_saltlen;
3362 3372                                          bcopy(buf_ptr, (uint8_t *)newbie->
3363 3373                                              ipsa_iv, SADB_1TO8(ekey->
3364 3374                                              sadb_key_reserved));
3365 3375                                  } else {
3366 3376                                          (void) random_get_pseudo_bytes(
3367 3377                                              (uint8_t *)newbie->ipsa_iv,
3368 3378                                              newbie->ipsa_iv_len);
3369 3379                                  }
3370 3380                                  newbie->ipsa_iv_softexpire =
3371 3381                                      (*newbie->ipsa_iv) << 9;
3372 3382                                  newbie->ipsa_iv_hardexpire = *newbie->ipsa_iv;
3373 3383                          }
3374 3384                  }
3375 3385                  bzero((ekey + 1), SADB_1TO8(ekey->sadb_key_bits));
3376 3386  
3377 3387                  /*
3378 3388                   * Pre-initialize the kernel crypto framework key
3379 3389                   * structure.
3380 3390                   */
3381 3391                  newbie->ipsa_kcfencrkey.ck_format = CRYPTO_KEY_RAW;
3382 3392                  newbie->ipsa_kcfencrkey.ck_length = newbie->ipsa_encrkeybits;
3383 3393                  newbie->ipsa_kcfencrkey.ck_data = newbie->ipsa_encrkey;
3384 3394  
3385 3395                  rw_enter(&ipss->ipsec_alg_lock, RW_READER);
3386 3396                  error = ipsec_create_ctx_tmpl(newbie, IPSEC_ALG_ENCR);
3387 3397                  rw_exit(&ipss->ipsec_alg_lock);
3388 3398                  if (error != 0) {
3389 3399                          mutex_exit(&newbie->ipsa_lock);
3390 3400                          /* See above for error explanation. */
3391 3401                          *diagnostic = SADB_X_DIAGNOSTIC_BAD_CTX;
3392 3402                          goto error;
3393 3403                  }
3394 3404          }
3395 3405  
3396 3406          if (async)
3397 3407                  newbie->ipsa_flags |= IPSA_F_ASYNC;
3398 3408  
3399 3409          /*
3400 3410           * Ptrs to processing functions.
3401 3411           */
3402 3412          if (newbie->ipsa_type == SADB_SATYPE_ESP)
3403 3413                  ipsecesp_init_funcs(newbie);
3404 3414          else
3405 3415                  ipsecah_init_funcs(newbie);
3406 3416          ASSERT(newbie->ipsa_output_func != NULL &&
3407 3417              newbie->ipsa_input_func != NULL);
3408 3418  
3409 3419          /*
3410 3420           * Certificate ID stuff.
3411 3421           */
3412 3422          if (ksi->ks_in_extv[SADB_EXT_IDENTITY_SRC] != NULL) {
3413 3423                  sadb_ident_t *id =
3414 3424                      (sadb_ident_t *)ksi->ks_in_extv[SADB_EXT_IDENTITY_SRC];
3415 3425  
3416 3426                  /*
3417 3427                   * Can assume strlen() will return okay because ext_check() in
3418 3428                   * keysock.c prepares the string for us.
3419 3429                   */
3420 3430                  newbie->ipsa_src_cid = ipsid_lookup(id->sadb_ident_type,
3421 3431                      (char *)(id+1), ns);
3422 3432                  if (newbie->ipsa_src_cid == NULL) {
3423 3433                          error = ENOMEM;
3424 3434                          mutex_exit(&newbie->ipsa_lock);
3425 3435                          goto error;
3426 3436                  }
3427 3437          }
3428 3438  
3429 3439          if (ksi->ks_in_extv[SADB_EXT_IDENTITY_DST] != NULL) {
3430 3440                  sadb_ident_t *id =
3431 3441                      (sadb_ident_t *)ksi->ks_in_extv[SADB_EXT_IDENTITY_DST];
3432 3442  
3433 3443                  /*
3434 3444                   * Can assume strlen() will return okay because ext_check() in
3435 3445                   * keysock.c prepares the string for us.
3436 3446                   */
3437 3447                  newbie->ipsa_dst_cid = ipsid_lookup(id->sadb_ident_type,
3438 3448                      (char *)(id+1), ns);
3439 3449                  if (newbie->ipsa_dst_cid == NULL) {
3440 3450                          error = ENOMEM;
3441 3451                          mutex_exit(&newbie->ipsa_lock);
3442 3452                          goto error;
3443 3453                  }
3444 3454          }
3445 3455  
3446 3456          /*
3447 3457           * sensitivity label handling code:
3448 3458           * Convert sens + bitmap into cred_t, and associate it
3449 3459           * with the new SA.
3450 3460           */
3451 3461          if (sens != NULL) {
3452 3462                  uint64_t *bitmap = (uint64_t *)(sens + 1);
3453 3463  
3454 3464                  newbie->ipsa_tsl = sadb_label_from_sens(sens, bitmap);
3455 3465          }
3456 3466  
3457 3467          /*
3458 3468           * Likewise for outer sensitivity.
3459 3469           */
3460 3470          if (osens != NULL) {
3461 3471                  uint64_t *bitmap = (uint64_t *)(osens + 1);
3462 3472                  ts_label_t *tsl, *effective_tsl;
3463 3473                  uint32_t *peer_addr_ptr;
3464 3474                  zoneid_t zoneid = GLOBAL_ZONEID;
3465 3475                  zone_t *zone;
3466 3476  
3467 3477                  peer_addr_ptr = is_inbound ? src_addr_ptr : dst_addr_ptr;
3468 3478  
3469 3479                  tsl = sadb_label_from_sens(osens, bitmap);
3470 3480                  newbie->ipsa_mac_exempt = CONN_MAC_DEFAULT;
3471 3481  
3472 3482                  if (osens->sadb_x_sens_flags & SADB_X_SENS_IMPLICIT) {
3473 3483                          newbie->ipsa_mac_exempt = CONN_MAC_IMPLICIT;
3474 3484                  }
3475 3485  
3476 3486                  error = tsol_check_dest(tsl, peer_addr_ptr,
3477 3487                      (af == AF_INET6)?IPV6_VERSION:IPV4_VERSION,
3478 3488                      newbie->ipsa_mac_exempt, B_TRUE, &effective_tsl);
3479 3489                  if (error != 0) {
3480 3490                          label_rele(tsl);
3481 3491                          mutex_exit(&newbie->ipsa_lock);
3482 3492                          goto error;
3483 3493                  }
3484 3494  
3485 3495                  if (effective_tsl != NULL) {
3486 3496                          label_rele(tsl);
3487 3497                          tsl = effective_tsl;
3488 3498                  }
3489 3499  
3490 3500                  newbie->ipsa_otsl = tsl;
3491 3501  
3492 3502                  zone = zone_find_by_label(tsl);
3493 3503                  if (zone != NULL) {
3494 3504                          zoneid = zone->zone_id;
3495 3505                          zone_rele(zone);
3496 3506                  }
3497 3507                  /*
3498 3508                   * For exclusive stacks we set the zoneid to zero to operate
3499 3509                   * as if in the global zone for tsol_compute_label_v4/v6
3500 3510                   */
3501 3511                  if (ipst->ips_netstack->netstack_stackid != GLOBAL_NETSTACKID)
3502 3512                          zoneid = GLOBAL_ZONEID;
3503 3513  
3504 3514                  if (af == AF_INET6) {
3505 3515                          error = tsol_compute_label_v6(tsl, zoneid,
3506 3516                              (in6_addr_t *)peer_addr_ptr,
3507 3517                              newbie->ipsa_opt_storage, ipst);
3508 3518                  } else {
3509 3519                          error = tsol_compute_label_v4(tsl, zoneid,
3510 3520                              *peer_addr_ptr, newbie->ipsa_opt_storage, ipst);
3511 3521                  }
3512 3522                  if (error != 0) {
3513 3523                          mutex_exit(&newbie->ipsa_lock);
3514 3524                          goto error;
3515 3525                  }
3516 3526          }
3517 3527  
3518 3528  
3519 3529          if (replayext != NULL) {
3520 3530                  if ((replayext->sadb_x_rc_replay32 == 0) &&
3521 3531                      (replayext->sadb_x_rc_replay64 != 0)) {
3522 3532                          error = EOPNOTSUPP;
3523 3533                          *diagnostic = SADB_X_DIAGNOSTIC_INVALID_REPLAY;
3524 3534                          mutex_exit(&newbie->ipsa_lock);
3525 3535                          goto error;
3526 3536                  }
3527 3537                  newbie->ipsa_replay = replayext->sadb_x_rc_replay32;
3528 3538          }
3529 3539  
3530 3540          /* now that the SA has been updated, set its new state */
3531 3541          newbie->ipsa_state = assoc->sadb_sa_state;
3532 3542  
3533 3543          if (clone) {
3534 3544                  newbie->ipsa_haspeer = B_TRUE;
3535 3545          } else {
3536 3546                  if (!is_inbound) {
3537 3547                          lifetime_fuzz(newbie);
3538 3548                  }
3539 3549          }
3540 3550          /*
3541 3551           * The less locks I hold when doing an insertion and possible cloning,
3542 3552           * the better!
3543 3553           */
3544 3554          mutex_exit(&newbie->ipsa_lock);
3545 3555  
3546 3556          if (clone) {
3547 3557                  newbie_clone = sadb_cloneassoc(newbie);
3548 3558  
3549 3559                  if (newbie_clone == NULL) {
3550 3560                          error = ENOMEM;
3551 3561                          goto error;
3552 3562                  }
3553 3563          }
3554 3564  
3555 3565          /*
3556 3566           * Enter the bucket locks.  The order of entry is outbound,
3557 3567           * inbound.  We map "primary" and "secondary" into outbound and inbound
3558 3568           * based on the destination address type.  If the destination address
3559 3569           * type is for a node that isn't mine (or potentially mine), the
3560 3570           * "primary" bucket is the outbound one.
3561 3571           */
3562 3572          if (!is_inbound) {
3563 3573                  /* primary == outbound */
3564 3574                  mutex_enter(&primary->isaf_lock);
3565 3575                  mutex_enter(&secondary->isaf_lock);
3566 3576          } else {
3567 3577                  /* primary == inbound */
3568 3578                  mutex_enter(&secondary->isaf_lock);
3569 3579                  mutex_enter(&primary->isaf_lock);
3570 3580          }
3571 3581  
3572 3582          /*
3573 3583           * sadb_insertassoc() doesn't increment the reference
3574 3584           * count.  We therefore have to increment the
3575 3585           * reference count one more time to reflect the
3576 3586           * pointers of the table that reference this SA.
3577 3587           */
3578 3588          IPSA_REFHOLD(newbie);
3579 3589  
3580 3590          if (isupdate) {
3581 3591                  /*
3582 3592                   * Unlink from larval holding cell in the "inbound" fanout.
3583 3593                   */
3584 3594                  ASSERT(newbie->ipsa_linklock == &primary->isaf_lock ||
3585 3595                      newbie->ipsa_linklock == &secondary->isaf_lock);
3586 3596                  sadb_unlinkassoc(newbie);
3587 3597          }
3588 3598  
3589 3599          mutex_enter(&newbie->ipsa_lock);
3590 3600          error = sadb_insertassoc(newbie, primary);
3591 3601          mutex_exit(&newbie->ipsa_lock);
3592 3602  
3593 3603          if (error != 0) {
3594 3604                  /*
3595 3605                   * Since sadb_insertassoc() failed, we must decrement the
3596 3606                   * refcount again so the cleanup code will actually free
3597 3607                   * the offending SA.
3598 3608                   */
3599 3609                  IPSA_REFRELE(newbie);
3600 3610                  goto error_unlock;
3601 3611          }
3602 3612  
3603 3613          if (newbie_clone != NULL) {
3604 3614                  mutex_enter(&newbie_clone->ipsa_lock);
3605 3615                  error = sadb_insertassoc(newbie_clone, secondary);
3606 3616                  mutex_exit(&newbie_clone->ipsa_lock);
3607 3617                  if (error != 0) {
3608 3618                          /* Collision in secondary table. */
3609 3619                          sadb_unlinkassoc(newbie);  /* This does REFRELE. */
3610 3620                          goto error_unlock;
3611 3621                  }
3612 3622                  IPSA_REFHOLD(newbie_clone);
3613 3623          } else {
3614 3624                  ASSERT(primary != secondary);
3615 3625                  scratch = ipsec_getassocbyspi(secondary, newbie->ipsa_spi,
3616 3626                      ALL_ZEROES_PTR, newbie->ipsa_dstaddr, af);
3617 3627                  if (scratch != NULL) {
3618 3628                          /* Collision in secondary table. */
3619 3629                          sadb_unlinkassoc(newbie);  /* This does REFRELE. */
3620 3630                          /* Set the error, since ipsec_getassocbyspi() can't. */
3621 3631                          error = EEXIST;
3622 3632                          goto error_unlock;
3623 3633                  }
3624 3634          }
3625 3635  
3626 3636          /* OKAY!  So let's do some reality check assertions. */
3627 3637  
3628 3638          ASSERT(MUTEX_NOT_HELD(&newbie->ipsa_lock));
3629 3639          ASSERT(newbie_clone == NULL ||
3630 3640              (MUTEX_NOT_HELD(&newbie_clone->ipsa_lock)));
3631 3641  
3632 3642  error_unlock:
3633 3643  
3634 3644          /*
3635 3645           * We can exit the locks in any order.  Only entrance needs to
3636 3646           * follow any protocol.
3637 3647           */
3638 3648          mutex_exit(&secondary->isaf_lock);
3639 3649          mutex_exit(&primary->isaf_lock);
3640 3650  
3641 3651          if (pair_ext != NULL && error == 0) {
3642 3652                  /* update pair_spi if it exists. */
3643 3653                  ipsa_query_t sq;
3644 3654  
3645 3655                  sq.spp = spp;           /* XXX param */
3646 3656                  error = sadb_form_query(ksi, IPSA_Q_DST, IPSA_Q_SRC|IPSA_Q_DST|
3647 3657                      IPSA_Q_SA|IPSA_Q_INBOUND|IPSA_Q_OUTBOUND, &sq, diagnostic);
3648 3658                  if (error)
3649 3659                          return (error);
3650 3660  
3651 3661                  error = get_ipsa_pair(&sq, &ipsapp, diagnostic);
3652 3662  
3653 3663                  if (error != 0)
3654 3664                          goto error;
3655 3665  
3656 3666                  if (ipsapp.ipsap_psa_ptr != NULL) {
3657 3667                          *diagnostic = SADB_X_DIAGNOSTIC_PAIR_ALREADY;
3658 3668                          error = EINVAL;
3659 3669                  } else {
3660 3670                          /* update_pairing() sets diagnostic */
3661 3671                          error = update_pairing(&ipsapp, &sq, ksi, diagnostic);
3662 3672                  }
3663 3673          }
3664 3674          /* Common error point for this routine. */
3665 3675  error:
3666 3676          if (newbie != NULL) {
3667 3677                  if (error != 0) {
3668 3678                          /* This SA is broken, let the reaper clean up. */
3669 3679                          mutex_enter(&newbie->ipsa_lock);
3670 3680                          newbie->ipsa_state = IPSA_STATE_DEAD;
3671 3681                          newbie->ipsa_hardexpiretime = 1;
3672 3682                          mutex_exit(&newbie->ipsa_lock);
3673 3683                  }
3674 3684                  IPSA_REFRELE(newbie);
3675 3685          }
3676 3686          if (newbie_clone != NULL) {
3677 3687                  IPSA_REFRELE(newbie_clone);
3678 3688          }
3679 3689  
3680 3690          if (error == 0) {
3681 3691                  /*
3682 3692                   * Construct favorable PF_KEY return message and send to
3683 3693                   * keysock. Update the flags in the original keysock message
3684 3694                   * to reflect the actual flags in the new SA.
3685 3695                   *  (Q:  Do I need to pass "newbie"?  If I do,
3686 3696                   * make sure to REFHOLD, call, then REFRELE.)
3687 3697                   */
3688 3698                  assoc->sadb_sa_flags = newbie->ipsa_flags;
3689 3699                  sadb_pfkey_echo(pfkey_q, mp, samsg, ksi, NULL);
3690 3700          }
3691 3701  
3692 3702          destroy_ipsa_pair(&ipsapp);
3693 3703          return (error);
3694 3704  }
3695 3705  
3696 3706  /*
3697 3707   * Set the time of first use for a security association.  Update any
3698 3708   * expiration times as a result.
3699 3709   */
3700 3710  void
3701 3711  sadb_set_usetime(ipsa_t *assoc)
3702 3712  {
3703 3713          time_t snapshot = gethrestime_sec();
3704 3714  
3705 3715          mutex_enter(&assoc->ipsa_lock);
3706 3716          assoc->ipsa_lastuse = snapshot;
3707 3717          assoc->ipsa_idleexpiretime = snapshot + assoc->ipsa_idletime;
3708 3718  
3709 3719          /*
3710 3720           * Caller does check usetime before calling me usually, and
3711 3721           * double-checking is better than a mutex_enter/exit hit.
3712 3722           */
3713 3723          if (assoc->ipsa_usetime == 0) {
3714 3724                  /*
3715 3725                   * This is redundant for outbound SA's, as
3716 3726                   * ipsec_getassocbyconn() sets the IPSA_F_USED flag already.
3717 3727                   * Inbound SAs, however, have no such protection.
3718 3728                   */
3719 3729                  assoc->ipsa_flags |= IPSA_F_USED;
3720 3730                  assoc->ipsa_usetime = snapshot;
3721 3731  
3722 3732                  /*
3723 3733                   * After setting the use time, see if we have a use lifetime
3724 3734                   * that would cause the actual SA expiration time to shorten.
3725 3735                   */
3726 3736                  UPDATE_EXPIRE(assoc, softuselt, softexpiretime);
3727 3737                  UPDATE_EXPIRE(assoc, harduselt, hardexpiretime);
3728 3738          }
3729 3739          mutex_exit(&assoc->ipsa_lock);
3730 3740  }
3731 3741  
3732 3742  /*
3733 3743   * Send up a PF_KEY expire message for this association.
3734 3744   */
3735 3745  static void
3736 3746  sadb_expire_assoc(queue_t *pfkey_q, ipsa_t *assoc)
3737 3747  {
3738 3748          mblk_t *mp, *mp1;
3739 3749          int alloclen, af;
3740 3750          sadb_msg_t *samsg;
3741 3751          sadb_lifetime_t *current, *expire;
3742 3752          sadb_sa_t *saext;
3743 3753          uint8_t *end;
3744 3754          boolean_t tunnel_mode;
3745 3755  
3746 3756          ASSERT(MUTEX_HELD(&assoc->ipsa_lock));
3747 3757  
3748 3758          /* Don't bother sending if there's no queue. */
3749 3759          if (pfkey_q == NULL)
3750 3760                  return;
3751 3761  
3752 3762          mp = sadb_keysock_out(0);
3753 3763          if (mp == NULL) {
3754 3764                  /* cmn_err(CE_WARN, */
3755 3765                  /*      "sadb_expire_assoc: Can't allocate KEYSOCK_OUT.\n"); */
3756 3766                  return;
3757 3767          }
3758 3768  
3759 3769          alloclen = sizeof (*samsg) + sizeof (*current) + sizeof (*expire) +
3760 3770              2 * sizeof (sadb_address_t) + sizeof (*saext);
3761 3771  
3762 3772          af = assoc->ipsa_addrfam;
3763 3773          switch (af) {
3764 3774          case AF_INET:
3765 3775                  alloclen += 2 * sizeof (struct sockaddr_in);
3766 3776                  break;
3767 3777          case AF_INET6:
3768 3778                  alloclen += 2 * sizeof (struct sockaddr_in6);
3769 3779                  break;
3770 3780          default:
3771 3781                  /* Won't happen unless there's a kernel bug. */
3772 3782                  freeb(mp);
3773 3783                  cmn_err(CE_WARN,
3774 3784                      "sadb_expire_assoc: Unknown address length.\n");
3775 3785                  return;
3776 3786          }
3777 3787  
3778 3788          tunnel_mode = (assoc->ipsa_flags & IPSA_F_TUNNEL);
3779 3789          if (tunnel_mode) {
3780 3790                  alloclen += 2 * sizeof (sadb_address_t);
3781 3791                  switch (assoc->ipsa_innerfam) {
3782 3792                  case AF_INET:
3783 3793                          alloclen += 2 * sizeof (struct sockaddr_in);
3784 3794                          break;
3785 3795                  case AF_INET6:
3786 3796                          alloclen += 2 * sizeof (struct sockaddr_in6);
3787 3797                          break;
3788 3798                  default:
3789 3799                          /* Won't happen unless there's a kernel bug. */
3790 3800                          freeb(mp);
3791 3801                          cmn_err(CE_WARN, "sadb_expire_assoc: "
3792 3802                              "Unknown inner address length.\n");
3793 3803                          return;
3794 3804                  }
3795 3805          }
3796 3806  
3797 3807          mp->b_cont = allocb(alloclen, BPRI_HI);
3798 3808          if (mp->b_cont == NULL) {
3799 3809                  freeb(mp);
3800 3810                  /* cmn_err(CE_WARN, */
3801 3811                  /*      "sadb_expire_assoc: Can't allocate message.\n"); */
3802 3812                  return;
3803 3813          }
3804 3814  
3805 3815          mp1 = mp;
3806 3816          mp = mp->b_cont;
3807 3817          end = mp->b_wptr + alloclen;
3808 3818  
3809 3819          samsg = (sadb_msg_t *)mp->b_wptr;
3810 3820          mp->b_wptr += sizeof (*samsg);
3811 3821          samsg->sadb_msg_version = PF_KEY_V2;
3812 3822          samsg->sadb_msg_type = SADB_EXPIRE;
3813 3823          samsg->sadb_msg_errno = 0;
3814 3824          samsg->sadb_msg_satype = assoc->ipsa_type;
3815 3825          samsg->sadb_msg_len = SADB_8TO64(alloclen);
3816 3826          samsg->sadb_msg_reserved = 0;
3817 3827          samsg->sadb_msg_seq = 0;
3818 3828          samsg->sadb_msg_pid = 0;
3819 3829  
3820 3830          saext = (sadb_sa_t *)mp->b_wptr;
3821 3831          mp->b_wptr += sizeof (*saext);
3822 3832          saext->sadb_sa_len = SADB_8TO64(sizeof (*saext));
3823 3833          saext->sadb_sa_exttype = SADB_EXT_SA;
3824 3834          saext->sadb_sa_spi = assoc->ipsa_spi;
3825 3835          saext->sadb_sa_replay = assoc->ipsa_replay_wsize;
3826 3836          saext->sadb_sa_state = assoc->ipsa_state;
3827 3837          saext->sadb_sa_auth = assoc->ipsa_auth_alg;
3828 3838          saext->sadb_sa_encrypt = assoc->ipsa_encr_alg;
3829 3839          saext->sadb_sa_flags = assoc->ipsa_flags;
3830 3840  
3831 3841          current = (sadb_lifetime_t *)mp->b_wptr;
3832 3842          mp->b_wptr += sizeof (sadb_lifetime_t);
3833 3843          current->sadb_lifetime_len = SADB_8TO64(sizeof (*current));
3834 3844          current->sadb_lifetime_exttype = SADB_EXT_LIFETIME_CURRENT;
3835 3845          /* We do not support the concept. */
3836 3846          current->sadb_lifetime_allocations = 0;
3837 3847          current->sadb_lifetime_bytes = assoc->ipsa_bytes;
3838 3848          current->sadb_lifetime_addtime = assoc->ipsa_addtime;
3839 3849          current->sadb_lifetime_usetime = assoc->ipsa_usetime;
3840 3850  
3841 3851          expire = (sadb_lifetime_t *)mp->b_wptr;
3842 3852          mp->b_wptr += sizeof (*expire);
3843 3853          expire->sadb_lifetime_len = SADB_8TO64(sizeof (*expire));
3844 3854  
3845 3855          if (assoc->ipsa_state == IPSA_STATE_DEAD) {
3846 3856                  expire->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
3847 3857                  expire->sadb_lifetime_allocations = assoc->ipsa_hardalloc;
3848 3858                  expire->sadb_lifetime_bytes = assoc->ipsa_hardbyteslt;
3849 3859                  expire->sadb_lifetime_addtime = assoc->ipsa_hardaddlt;
3850 3860                  expire->sadb_lifetime_usetime = assoc->ipsa_harduselt;
3851 3861          } else if (assoc->ipsa_state == IPSA_STATE_DYING) {
3852 3862                  expire->sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
3853 3863                  expire->sadb_lifetime_allocations = assoc->ipsa_softalloc;
3854 3864                  expire->sadb_lifetime_bytes = assoc->ipsa_softbyteslt;
3855 3865                  expire->sadb_lifetime_addtime = assoc->ipsa_softaddlt;
3856 3866                  expire->sadb_lifetime_usetime = assoc->ipsa_softuselt;
3857 3867          } else {
3858 3868                  ASSERT(assoc->ipsa_state == IPSA_STATE_MATURE);
3859 3869                  expire->sadb_lifetime_exttype = SADB_X_EXT_LIFETIME_IDLE;
3860 3870                  expire->sadb_lifetime_allocations = 0;
3861 3871                  expire->sadb_lifetime_bytes = 0;
3862 3872                  expire->sadb_lifetime_addtime = assoc->ipsa_idleaddlt;
3863 3873                  expire->sadb_lifetime_usetime = assoc->ipsa_idleuselt;
3864 3874          }
3865 3875  
3866 3876          mp->b_wptr = sadb_make_addr_ext(mp->b_wptr, end, SADB_EXT_ADDRESS_SRC,
3867 3877              af, assoc->ipsa_srcaddr, tunnel_mode ? 0 : SA_SRCPORT(assoc),
3868 3878              SA_PROTO(assoc), 0);
3869 3879          ASSERT(mp->b_wptr != NULL);
3870 3880  
3871 3881          mp->b_wptr = sadb_make_addr_ext(mp->b_wptr, end, SADB_EXT_ADDRESS_DST,
3872 3882              af, assoc->ipsa_dstaddr, tunnel_mode ? 0 : SA_DSTPORT(assoc),
3873 3883              SA_PROTO(assoc), 0);
3874 3884          ASSERT(mp->b_wptr != NULL);
3875 3885  
3876 3886          if (tunnel_mode) {
3877 3887                  mp->b_wptr = sadb_make_addr_ext(mp->b_wptr, end,
3878 3888                      SADB_X_EXT_ADDRESS_INNER_SRC, assoc->ipsa_innerfam,
3879 3889                      assoc->ipsa_innersrc, SA_SRCPORT(assoc), SA_IPROTO(assoc),
3880 3890                      assoc->ipsa_innersrcpfx);
3881 3891                  ASSERT(mp->b_wptr != NULL);
3882 3892                  mp->b_wptr = sadb_make_addr_ext(mp->b_wptr, end,
3883 3893                      SADB_X_EXT_ADDRESS_INNER_DST, assoc->ipsa_innerfam,
3884 3894                      assoc->ipsa_innerdst, SA_DSTPORT(assoc), SA_IPROTO(assoc),
3885 3895                      assoc->ipsa_innerdstpfx);
3886 3896                  ASSERT(mp->b_wptr != NULL);
3887 3897          }
3888 3898  
3889 3899          /* Can just putnext, we're ready to go! */
3890 3900          putnext(pfkey_q, mp1);
3891 3901  }
3892 3902  
3893 3903  /*
3894 3904   * "Age" the SA with the number of bytes that was used to protect traffic.
3895 3905   * Send an SADB_EXPIRE message if appropriate.  Return B_TRUE if there was
3896 3906   * enough "charge" left in the SA to protect the data.  Return B_FALSE
3897 3907   * otherwise.  (If B_FALSE is returned, the association either was, or became
3898 3908   * DEAD.)
3899 3909   */
3900 3910  boolean_t
3901 3911  sadb_age_bytes(queue_t *pfkey_q, ipsa_t *assoc, uint64_t bytes,
3902 3912      boolean_t sendmsg)
3903 3913  {
3904 3914          boolean_t rc = B_TRUE;
3905 3915          uint64_t newtotal;
3906 3916  
3907 3917          mutex_enter(&assoc->ipsa_lock);
3908 3918          newtotal = assoc->ipsa_bytes + bytes;
3909 3919          if (assoc->ipsa_hardbyteslt != 0 &&
3910 3920              newtotal >= assoc->ipsa_hardbyteslt) {
3911 3921                  if (assoc->ipsa_state != IPSA_STATE_DEAD) {
3912 3922                          sadb_delete_cluster(assoc);
3913 3923                          /*
3914 3924                           * Send EXPIRE message to PF_KEY.  May wish to pawn
3915 3925                           * this off on another non-interrupt thread.  Also
3916 3926                           * unlink this SA immediately.
3917 3927                           */
3918 3928                          assoc->ipsa_state = IPSA_STATE_DEAD;
3919 3929                          if (sendmsg)
3920 3930                                  sadb_expire_assoc(pfkey_q, assoc);
3921 3931                          /*
3922 3932                           * Set non-zero expiration time so sadb_age_assoc()
3923 3933                           * will work when reaping.
3924 3934                           */
3925 3935                          assoc->ipsa_hardexpiretime = (time_t)1;
3926 3936                  } /* Else someone beat me to it! */
3927 3937                  rc = B_FALSE;
3928 3938          } else if (assoc->ipsa_softbyteslt != 0 &&
3929 3939              (newtotal >= assoc->ipsa_softbyteslt)) {
3930 3940                  if (assoc->ipsa_state < IPSA_STATE_DYING) {
3931 3941                          /*
3932 3942                           * Send EXPIRE message to PF_KEY.  May wish to pawn
3933 3943                           * this off on another non-interrupt thread.
3934 3944                           */
3935 3945                          assoc->ipsa_state = IPSA_STATE_DYING;
3936 3946                          assoc->ipsa_bytes = newtotal;
3937 3947                          if (sendmsg)
3938 3948                                  sadb_expire_assoc(pfkey_q, assoc);
3939 3949                  } /* Else someone beat me to it! */
3940 3950          }
3941 3951          if (rc == B_TRUE)
3942 3952                  assoc->ipsa_bytes = newtotal;
3943 3953          mutex_exit(&assoc->ipsa_lock);
3944 3954          return (rc);
3945 3955  }
3946 3956  
3947 3957  /*
3948 3958   * "Torch" an individual SA.  Returns NULL, so it can be tail-called from
3949 3959   *     sadb_age_assoc().
3950 3960   */
3951 3961  static ipsa_t *
3952 3962  sadb_torch_assoc(isaf_t *head, ipsa_t *sa)
3953 3963  {
3954 3964          ASSERT(MUTEX_HELD(&head->isaf_lock));
3955 3965          ASSERT(MUTEX_HELD(&sa->ipsa_lock));
3956 3966          ASSERT(sa->ipsa_state == IPSA_STATE_DEAD);
3957 3967  
3958 3968          /*
3959 3969           * Force cached SAs to be revalidated..
3960 3970           */
3961 3971          head->isaf_gen++;
3962 3972  
3963 3973          mutex_exit(&sa->ipsa_lock);
3964 3974          sadb_unlinkassoc(sa);
3965 3975  
3966 3976          return (NULL);
3967 3977  }
3968 3978  
3969 3979  /*
3970 3980   * Do various SA-is-idle activities depending on delta (the number of idle
3971 3981   * seconds on the SA) and/or other properties of the SA.
3972 3982   *
3973 3983   * Return B_TRUE if I've sent a packet, because I have to drop the
3974 3984   * association's mutex before sending a packet out the wire.
3975 3985   */
3976 3986  /* ARGSUSED */
3977 3987  static boolean_t
3978 3988  sadb_idle_activities(ipsa_t *assoc, time_t delta, boolean_t inbound)
3979 3989  {
3980 3990          ipsecesp_stack_t *espstack = assoc->ipsa_netstack->netstack_ipsecesp;
3981 3991          int nat_t_interval = espstack->ipsecesp_nat_keepalive_interval;
3982 3992  
3983 3993          ASSERT(MUTEX_HELD(&assoc->ipsa_lock));
3984 3994  
3985 3995          if (!inbound && (assoc->ipsa_flags & IPSA_F_NATT_LOC) &&
3986 3996              delta >= nat_t_interval &&
3987 3997              gethrestime_sec() - assoc->ipsa_last_nat_t_ka >= nat_t_interval) {
3988 3998                  ASSERT(assoc->ipsa_type == SADB_SATYPE_ESP);
3989 3999                  assoc->ipsa_last_nat_t_ka = gethrestime_sec();
3990 4000                  mutex_exit(&assoc->ipsa_lock);
3991 4001                  ipsecesp_send_keepalive(assoc);
3992 4002                  return (B_TRUE);
3993 4003          }
3994 4004          return (B_FALSE);
3995 4005  }
3996 4006  
3997 4007  /*
3998 4008   * Return "assoc" if haspeer is true and I send an expire.  This allows
3999 4009   * the consumers' aging functions to tidy up an expired SA's peer.
4000 4010   */
4001 4011  static ipsa_t *
4002 4012  sadb_age_assoc(isaf_t *head, queue_t *pfkey_q, ipsa_t *assoc,
4003 4013      time_t current, int reap_delay, boolean_t inbound)
4004 4014  {
4005 4015          ipsa_t *retval = NULL;
4006 4016          boolean_t dropped_mutex = B_FALSE;
4007 4017  
4008 4018          ASSERT(MUTEX_HELD(&head->isaf_lock));
4009 4019  
4010 4020          mutex_enter(&assoc->ipsa_lock);
4011 4021  
4012 4022          if (((assoc->ipsa_state == IPSA_STATE_LARVAL) ||
4013 4023              ((assoc->ipsa_state == IPSA_STATE_IDLE) ||
4014 4024              (assoc->ipsa_state == IPSA_STATE_ACTIVE_ELSEWHERE) &&
4015 4025              (assoc->ipsa_hardexpiretime != 0))) &&
4016 4026              (assoc->ipsa_hardexpiretime <= current)) {
4017 4027                  assoc->ipsa_state = IPSA_STATE_DEAD;
4018 4028                  return (sadb_torch_assoc(head, assoc));
4019 4029          }
4020 4030  
4021 4031          /*
4022 4032           * Check lifetimes.  Fortunately, SA setup is done
4023 4033           * such that there are only two times to look at,
4024 4034           * softexpiretime, and hardexpiretime.
4025 4035           *
4026 4036           * Check hard first.
4027 4037           */
4028 4038  
4029 4039          if (assoc->ipsa_hardexpiretime != 0 &&
4030 4040              assoc->ipsa_hardexpiretime <= current) {
4031 4041                  if (assoc->ipsa_state == IPSA_STATE_DEAD)
4032 4042                          return (sadb_torch_assoc(head, assoc));
4033 4043  
4034 4044                  if (inbound) {
4035 4045                          sadb_delete_cluster(assoc);
4036 4046                  }
4037 4047  
4038 4048                  /*
4039 4049                   * Send SADB_EXPIRE with hard lifetime, delay for unlinking.
4040 4050                   */
4041 4051                  assoc->ipsa_state = IPSA_STATE_DEAD;
4042 4052                  if (assoc->ipsa_haspeer || assoc->ipsa_otherspi != 0) {
4043 4053                          /*
4044 4054                           * If the SA is paired or peered with another, put
4045 4055                           * a copy on a list which can be processed later, the
4046 4056                           * pair/peer SA needs to be updated so the both die
4047 4057                           * at the same time.
4048 4058                           *
4049 4059                           * If I return assoc, I have to bump up its reference
4050 4060                           * count to keep with the ipsa_t reference count
4051 4061                           * semantics.
4052 4062                           */
4053 4063                          IPSA_REFHOLD(assoc);
4054 4064                          retval = assoc;
4055 4065                  }
4056 4066                  sadb_expire_assoc(pfkey_q, assoc);
4057 4067                  assoc->ipsa_hardexpiretime = current + reap_delay;
4058 4068          } else if (assoc->ipsa_softexpiretime != 0 &&
4059 4069              assoc->ipsa_softexpiretime <= current &&
4060 4070              assoc->ipsa_state < IPSA_STATE_DYING) {
4061 4071                  /*
4062 4072                   * Send EXPIRE message to PF_KEY.  May wish to pawn
4063 4073                   * this off on another non-interrupt thread.
4064 4074                   */
4065 4075                  assoc->ipsa_state = IPSA_STATE_DYING;
4066 4076                  if (assoc->ipsa_haspeer) {
4067 4077                          /*
4068 4078                           * If the SA has a peer, update the peer's state
4069 4079                           * on SOFT_EXPIRE, this is mostly to prevent two
4070 4080                           * expire messages from effectively the same SA.
4071 4081                           *
4072 4082                           * Don't care about paired SA's, then can (and should)
4073 4083                           * be able to soft expire at different times.
4074 4084                           *
4075 4085                           * If I return assoc, I have to bump up its
4076 4086                           * reference count to keep with the ipsa_t reference
4077 4087                           * count semantics.
4078 4088                           */
4079 4089                          IPSA_REFHOLD(assoc);
4080 4090                          retval = assoc;
4081 4091                  }
4082 4092                  sadb_expire_assoc(pfkey_q, assoc);
4083 4093          } else if (assoc->ipsa_idletime != 0 &&
4084 4094              assoc->ipsa_idleexpiretime <= current) {
4085 4095                  if (assoc->ipsa_state == IPSA_STATE_ACTIVE_ELSEWHERE) {
4086 4096                          assoc->ipsa_state = IPSA_STATE_IDLE;
4087 4097                  }
4088 4098  
4089 4099                  /*
4090 4100                   * Need to handle Mature case
4091 4101                   */
4092 4102                  if (assoc->ipsa_state == IPSA_STATE_MATURE) {
4093 4103                          sadb_expire_assoc(pfkey_q, assoc);
4094 4104                  }
4095 4105          } else {
4096 4106                  /* Check idle time activities. */
4097 4107                  dropped_mutex = sadb_idle_activities(assoc,
4098 4108                      current - assoc->ipsa_lastuse, inbound);
4099 4109          }
4100 4110  
4101 4111          if (!dropped_mutex)
4102 4112                  mutex_exit(&assoc->ipsa_lock);
4103 4113          return (retval);
4104 4114  }
4105 4115  
4106 4116  /*
4107 4117   * Called by a consumer protocol to do ther dirty work of reaping dead
4108 4118   * Security Associations.
4109 4119   *
4110 4120   * NOTE: sadb_age_assoc() marks expired SA's as DEAD but only removed
4111 4121   * SA's that are already marked DEAD, so expired SA's are only reaped
4112 4122   * the second time sadb_ager() runs.
4113 4123   */
4114 4124  void
4115 4125  sadb_ager(sadb_t *sp, queue_t *pfkey_q, int reap_delay, netstack_t *ns)
4116 4126  {
4117 4127          int i;
4118 4128          isaf_t *bucket;
4119 4129          ipsa_t *assoc, *spare;
4120 4130          iacqf_t *acqlist;
4121 4131          ipsacq_t *acqrec, *spareacq;
4122 4132          templist_t *haspeerlist, *newbie;
4123 4133          /* Snapshot current time now. */
4124 4134          time_t current = gethrestime_sec();
4125 4135          haspeerlist = NULL;
4126 4136  
4127 4137          /*
4128 4138           * Do my dirty work.  This includes aging real entries, aging
4129 4139           * larvals, and aging outstanding ACQUIREs.
4130 4140           *
4131 4141           * I hope I don't tie up resources for too long.
4132 4142           */
4133 4143  
4134 4144          /* Age acquires. */
4135 4145  
4136 4146          for (i = 0; i < sp->sdb_hashsize; i++) {
4137 4147                  acqlist = &sp->sdb_acq[i];
4138 4148                  mutex_enter(&acqlist->iacqf_lock);
4139 4149                  for (acqrec = acqlist->iacqf_ipsacq; acqrec != NULL;
4140 4150                      acqrec = spareacq) {
4141 4151                          spareacq = acqrec->ipsacq_next;
4142 4152                          if (current > acqrec->ipsacq_expire)
4143 4153                                  sadb_destroy_acquire(acqrec, ns);
4144 4154                  }
4145 4155                  mutex_exit(&acqlist->iacqf_lock);
4146 4156          }
4147 4157  
4148 4158          /* Age inbound associations. */
4149 4159          for (i = 0; i < sp->sdb_hashsize; i++) {
4150 4160                  bucket = &(sp->sdb_if[i]);
4151 4161                  mutex_enter(&bucket->isaf_lock);
4152 4162                  for (assoc = bucket->isaf_ipsa; assoc != NULL;
4153 4163                      assoc = spare) {
4154 4164                          spare = assoc->ipsa_next;
4155 4165                          if (sadb_age_assoc(bucket, pfkey_q, assoc, current,
4156 4166                              reap_delay, B_TRUE) != NULL) {
4157 4167                                  /*
4158 4168                                   * Put SA's which have a peer or SA's which
4159 4169                                   * are paired on a list for processing after
4160 4170                                   * all the hash tables have been walked.
4161 4171                                   *
4162 4172                                   * sadb_age_assoc() increments the refcnt,
4163 4173                                   * effectively doing an IPSA_REFHOLD().
4164 4174                                   */
4165 4175                                  newbie = kmem_alloc(sizeof (*newbie),
4166 4176                                      KM_NOSLEEP);
4167 4177                                  if (newbie == NULL) {
4168 4178                                          /*
4169 4179                                           * Don't forget to REFRELE().
4170 4180                                           */
4171 4181                                          IPSA_REFRELE(assoc);
4172 4182                                          continue;       /* for loop... */
4173 4183                                  }
4174 4184                                  newbie->next = haspeerlist;
4175 4185                                  newbie->ipsa = assoc;
4176 4186                                  haspeerlist = newbie;
4177 4187                          }
4178 4188                  }
4179 4189                  mutex_exit(&bucket->isaf_lock);
4180 4190          }
4181 4191  
4182 4192          age_pair_peer_list(haspeerlist, sp, B_FALSE);
4183 4193          haspeerlist = NULL;
4184 4194  
4185 4195          /* Age outbound associations. */
4186 4196          for (i = 0; i < sp->sdb_hashsize; i++) {
4187 4197                  bucket = &(sp->sdb_of[i]);
4188 4198                  mutex_enter(&bucket->isaf_lock);
4189 4199                  for (assoc = bucket->isaf_ipsa; assoc != NULL;
4190 4200                      assoc = spare) {
4191 4201                          spare = assoc->ipsa_next;
4192 4202                          if (sadb_age_assoc(bucket, pfkey_q, assoc, current,
4193 4203                              reap_delay, B_FALSE) != NULL) {
4194 4204                                  /*
4195 4205                                   * sadb_age_assoc() increments the refcnt,
4196 4206                                   * effectively doing an IPSA_REFHOLD().
4197 4207                                   */
4198 4208                                  newbie = kmem_alloc(sizeof (*newbie),
4199 4209                                      KM_NOSLEEP);
4200 4210                                  if (newbie == NULL) {
4201 4211                                          /*
4202 4212                                           * Don't forget to REFRELE().
4203 4213                                           */
4204 4214                                          IPSA_REFRELE(assoc);
4205 4215                                          continue;       /* for loop... */
4206 4216                                  }
4207 4217                                  newbie->next = haspeerlist;
4208 4218                                  newbie->ipsa = assoc;
4209 4219                                  haspeerlist = newbie;
4210 4220                          }
4211 4221                  }
4212 4222                  mutex_exit(&bucket->isaf_lock);
4213 4223          }
4214 4224  
4215 4225          age_pair_peer_list(haspeerlist, sp, B_TRUE);
4216 4226  
4217 4227          /*
4218 4228           * Run a GC pass to clean out dead identities.
4219 4229           */
4220 4230          ipsid_gc(ns);
4221 4231  }
4222 4232  
4223 4233  /*
4224 4234   * Figure out when to reschedule the ager.
4225 4235   */
4226 4236  timeout_id_t
4227 4237  sadb_retimeout(hrtime_t begin, queue_t *pfkey_q, void (*ager)(void *),
4228 4238      void *agerarg, uint_t *intp, uint_t intmax, short mid)
4229 4239  {
4230 4240          hrtime_t end = gethrtime();
4231 4241          uint_t interval = *intp;        /* "interval" is in ms. */
4232 4242  
4233 4243          /*
4234 4244           * See how long this took.  If it took too long, increase the
4235 4245           * aging interval.
4236 4246           */
4237 4247          if ((end - begin) > MSEC2NSEC(interval)) {
4238 4248                  if (interval >= intmax) {
4239 4249                          /* XXX Rate limit this?  Or recommend flush? */
4240 4250                          (void) strlog(mid, 0, 0, SL_ERROR | SL_WARN,
4241 4251                              "Too many SA's to age out in %d msec.\n",
4242 4252                              intmax);
4243 4253                  } else {
4244 4254                          /* Double by shifting by one bit. */
4245 4255                          interval <<= 1;
4246 4256                          interval = min(interval, intmax);
4247 4257                  }
4248 4258          } else if ((end - begin) <= (MSEC2NSEC(interval) / 2) &&
4249 4259              interval > SADB_AGE_INTERVAL_DEFAULT) {
4250 4260                  /*
4251 4261                   * If I took less than half of the interval, then I should
4252 4262                   * ratchet the interval back down.  Never automatically
4253 4263                   * shift below the default aging interval.
4254 4264                   *
4255 4265                   * NOTE:This even overrides manual setting of the age
4256 4266                   *      interval using NDD to lower the setting past the
4257 4267                   *      default.  In other words, if you set the interval
4258 4268                   *      lower than the default, and your SADB gets too big,
4259 4269                   *      the interval will only self-lower back to the default.
4260 4270                   */
4261 4271                  /* Halve by shifting one bit. */
4262 4272                  interval >>= 1;
4263 4273                  interval = max(interval, SADB_AGE_INTERVAL_DEFAULT);
4264 4274          }
4265 4275          *intp = interval;
4266 4276          return (qtimeout(pfkey_q, ager, agerarg,
4267 4277              drv_usectohz(interval * (MICROSEC / MILLISEC))));
4268 4278  }
4269 4279  
4270 4280  
4271 4281  /*
4272 4282   * Update the lifetime values of an SA.  This is the path an SADB_UPDATE
4273 4283   * message takes when updating a MATURE or DYING SA.
4274 4284   */
4275 4285  static void
4276 4286  sadb_update_lifetimes(ipsa_t *assoc, sadb_lifetime_t *hard,
4277 4287      sadb_lifetime_t *soft, sadb_lifetime_t *idle, boolean_t outbound)
4278 4288  {
4279 4289          mutex_enter(&assoc->ipsa_lock);
4280 4290  
4281 4291          /*
4282 4292           * XXX RFC 2367 mentions how an SADB_EXT_LIFETIME_CURRENT can be
4283 4293           * passed in during an update message.  We currently don't handle
4284 4294           * these.
4285 4295           */
4286 4296  
4287 4297          if (hard != NULL) {
4288 4298                  if (hard->sadb_lifetime_bytes != 0)
4289 4299                          assoc->ipsa_hardbyteslt = hard->sadb_lifetime_bytes;
4290 4300                  if (hard->sadb_lifetime_usetime != 0)
4291 4301                          assoc->ipsa_harduselt = hard->sadb_lifetime_usetime;
4292 4302                  if (hard->sadb_lifetime_addtime != 0)
4293 4303                          assoc->ipsa_hardaddlt = hard->sadb_lifetime_addtime;
4294 4304                  if (assoc->ipsa_hardaddlt != 0) {
4295 4305                          assoc->ipsa_hardexpiretime =
4296 4306                              assoc->ipsa_addtime + assoc->ipsa_hardaddlt;
4297 4307                  }
4298 4308                  if (assoc->ipsa_harduselt != 0 &&
4299 4309                      assoc->ipsa_flags & IPSA_F_USED) {
4300 4310                          UPDATE_EXPIRE(assoc, harduselt, hardexpiretime);
4301 4311                  }
4302 4312                  if (hard->sadb_lifetime_allocations != 0)
4303 4313                          assoc->ipsa_hardalloc = hard->sadb_lifetime_allocations;
4304 4314          }
4305 4315  
4306 4316          if (soft != NULL) {
4307 4317                  if (soft->sadb_lifetime_bytes != 0) {
4308 4318                          if (soft->sadb_lifetime_bytes >
4309 4319                              assoc->ipsa_hardbyteslt) {
4310 4320                                  assoc->ipsa_softbyteslt =
4311 4321                                      assoc->ipsa_hardbyteslt;
4312 4322                          } else {
4313 4323                                  assoc->ipsa_softbyteslt =
4314 4324                                      soft->sadb_lifetime_bytes;
4315 4325                          }
4316 4326                  }
4317 4327                  if (soft->sadb_lifetime_usetime != 0) {
4318 4328                          if (soft->sadb_lifetime_usetime >
4319 4329                              assoc->ipsa_harduselt) {
4320 4330                                  assoc->ipsa_softuselt =
4321 4331                                      assoc->ipsa_harduselt;
4322 4332                          } else {
4323 4333                                  assoc->ipsa_softuselt =
4324 4334                                      soft->sadb_lifetime_usetime;
4325 4335                          }
4326 4336                  }
4327 4337                  if (soft->sadb_lifetime_addtime != 0) {
4328 4338                          if (soft->sadb_lifetime_addtime >
4329 4339                              assoc->ipsa_hardexpiretime) {
4330 4340                                  assoc->ipsa_softexpiretime =
4331 4341                                      assoc->ipsa_hardexpiretime;
4332 4342                          } else {
4333 4343                                  assoc->ipsa_softaddlt =
4334 4344                                      soft->sadb_lifetime_addtime;
4335 4345                          }
4336 4346                  }
4337 4347                  if (assoc->ipsa_softaddlt != 0) {
4338 4348                          assoc->ipsa_softexpiretime =
4339 4349                              assoc->ipsa_addtime + assoc->ipsa_softaddlt;
4340 4350                  }
4341 4351                  if (assoc->ipsa_softuselt != 0 &&
4342 4352                      assoc->ipsa_flags & IPSA_F_USED) {
4343 4353                          UPDATE_EXPIRE(assoc, softuselt, softexpiretime);
4344 4354                  }
4345 4355                  if (outbound && assoc->ipsa_softexpiretime != 0) {
4346 4356                          if (assoc->ipsa_state == IPSA_STATE_MATURE)
4347 4357                                  lifetime_fuzz(assoc);
4348 4358                  }
4349 4359  
4350 4360                  if (soft->sadb_lifetime_allocations != 0)
4351 4361                          assoc->ipsa_softalloc = soft->sadb_lifetime_allocations;
4352 4362          }
4353 4363  
4354 4364          if (idle != NULL) {
4355 4365                  time_t current = gethrestime_sec();
4356 4366                  if ((assoc->ipsa_idleexpiretime <= current) &&
4357 4367                      (assoc->ipsa_idleaddlt == idle->sadb_lifetime_addtime)) {
4358 4368                          assoc->ipsa_idleexpiretime =
4359 4369                              current + assoc->ipsa_idleaddlt;
4360 4370                  }
4361 4371                  if (idle->sadb_lifetime_addtime != 0)
4362 4372                          assoc->ipsa_idleaddlt = idle->sadb_lifetime_addtime;
4363 4373                  if (idle->sadb_lifetime_usetime != 0)
4364 4374                          assoc->ipsa_idleuselt = idle->sadb_lifetime_usetime;
4365 4375                  if (assoc->ipsa_idleaddlt != 0) {
4366 4376                          assoc->ipsa_idleexpiretime =
4367 4377                              current + idle->sadb_lifetime_addtime;
4368 4378                          assoc->ipsa_idletime = idle->sadb_lifetime_addtime;
4369 4379                  }
4370 4380                  if (assoc->ipsa_idleuselt != 0) {
4371 4381                          if (assoc->ipsa_idletime != 0) {
4372 4382                                  assoc->ipsa_idletime = min(assoc->ipsa_idletime,
4373 4383                                      assoc->ipsa_idleuselt);
4374 4384                          assoc->ipsa_idleexpiretime =
4375 4385                              current + assoc->ipsa_idletime;
4376 4386                          } else {
4377 4387                                  assoc->ipsa_idleexpiretime =
4378 4388                                      current + assoc->ipsa_idleuselt;
4379 4389                                  assoc->ipsa_idletime = assoc->ipsa_idleuselt;
4380 4390                          }
4381 4391                  }
4382 4392          }
4383 4393          mutex_exit(&assoc->ipsa_lock);
4384 4394  }
4385 4395  
4386 4396  static int
4387 4397  sadb_update_state(ipsa_t *assoc, uint_t new_state, mblk_t **ipkt_lst)
4388 4398  {
4389 4399          int rcode = 0;
4390 4400          time_t current = gethrestime_sec();
4391 4401  
4392 4402          mutex_enter(&assoc->ipsa_lock);
4393 4403  
4394 4404          switch (new_state) {
4395 4405          case SADB_X_SASTATE_ACTIVE_ELSEWHERE:
4396 4406                  if (assoc->ipsa_state == SADB_X_SASTATE_IDLE) {
4397 4407                          assoc->ipsa_state = IPSA_STATE_ACTIVE_ELSEWHERE;
4398 4408                          assoc->ipsa_idleexpiretime =
4399 4409                              current + assoc->ipsa_idletime;
4400 4410                  }
4401 4411                  break;
4402 4412          case SADB_X_SASTATE_IDLE:
4403 4413                  if (assoc->ipsa_state == SADB_X_SASTATE_ACTIVE_ELSEWHERE) {
4404 4414                          assoc->ipsa_state = IPSA_STATE_IDLE;
4405 4415                          assoc->ipsa_idleexpiretime =
4406 4416                              current + assoc->ipsa_idletime;
4407 4417                  } else {
4408 4418                          rcode = EINVAL;
4409 4419                  }
4410 4420                  break;
4411 4421  
4412 4422          case SADB_X_SASTATE_ACTIVE:
4413 4423                  if (assoc->ipsa_state != SADB_X_SASTATE_IDLE) {
4414 4424                          rcode = EINVAL;
4415 4425                          break;
4416 4426                  }
4417 4427                  assoc->ipsa_state = IPSA_STATE_MATURE;
4418 4428                  assoc->ipsa_idleexpiretime = current + assoc->ipsa_idletime;
4419 4429  
4420 4430                  if (ipkt_lst == NULL) {
4421 4431                          break;
4422 4432                  }
4423 4433  
4424 4434                  if (assoc->ipsa_bpkt_head != NULL) {
4425 4435                          *ipkt_lst = assoc->ipsa_bpkt_head;
4426 4436                          assoc->ipsa_bpkt_head = assoc->ipsa_bpkt_tail = NULL;
4427 4437                          assoc->ipsa_mblkcnt = 0;
4428 4438                  } else {
4429 4439                          *ipkt_lst = NULL;
4430 4440                  }
4431 4441                  break;
4432 4442          default:
4433 4443                  rcode = EINVAL;
4434 4444                  break;
4435 4445          }
4436 4446  
4437 4447          mutex_exit(&assoc->ipsa_lock);
4438 4448          return (rcode);
4439 4449  }
4440 4450  
4441 4451  /*
4442 4452   * Check a proposed KMC update for sanity.
4443 4453   */
4444 4454  static int
4445 4455  sadb_check_kmc(ipsa_query_t *sq, ipsa_t *sa, int *diagnostic)
4446 4456  {
4447 4457          uint32_t kmp = sq->kmp;
4448 4458          uint64_t kmc = sq->kmc;
4449 4459  
4450 4460          if (sa == NULL)
4451 4461                  return (0);
4452 4462  
4453 4463          if (sa->ipsa_state == IPSA_STATE_DEAD)
4454 4464                  return (ESRCH); /* DEAD == Not there, in this case. */
4455 4465  
4456 4466          if ((kmp != 0) && (sa->ipsa_kmp != 0) && (sa->ipsa_kmp != kmp)) {
4457 4467                  *diagnostic = SADB_X_DIAGNOSTIC_DUPLICATE_KMP;
4458 4468                  return (EINVAL);
4459 4469          }
4460 4470  
4461 4471          if ((kmc != 0) && (sa->ipsa_kmc != 0) && (sa->ipsa_kmc != kmc)) {
4462 4472                  *diagnostic = SADB_X_DIAGNOSTIC_DUPLICATE_KMC;
4463 4473                  return (EINVAL);
4464 4474          }
4465 4475  
4466 4476          return (0);
4467 4477  }
4468 4478  
4469 4479  /*
4470 4480   * Actually update the KMC info.
4471 4481   */
4472 4482  static void
4473 4483  sadb_update_kmc(ipsa_query_t *sq, ipsa_t *sa)
4474 4484  {
4475 4485          uint32_t kmp = sq->kmp;
4476 4486          uint64_t kmc = sq->kmc;
4477 4487  
4478 4488          if (kmp != 0)
4479 4489                  sa->ipsa_kmp = kmp;
4480 4490          if (kmc != 0)
4481 4491                  sa->ipsa_kmc = kmc;
4482 4492  }
4483 4493  
4484 4494  /*
4485 4495   * Common code to update an SA.
4486 4496   */
4487 4497  
4488 4498  int
4489 4499  sadb_update_sa(mblk_t *mp, keysock_in_t *ksi, mblk_t **ipkt_lst,
4490 4500      sadbp_t *spp, int *diagnostic, queue_t *pfkey_q,
4491 4501      int (*add_sa_func)(mblk_t *, keysock_in_t *, int *, netstack_t *),
4492 4502      netstack_t *ns, uint8_t sadb_msg_type)
4493 4503  {
4494 4504          sadb_key_t *akey = (sadb_key_t *)ksi->ks_in_extv[SADB_EXT_KEY_AUTH];
4495 4505          sadb_key_t *ekey = (sadb_key_t *)ksi->ks_in_extv[SADB_EXT_KEY_ENCRYPT];
4496 4506          sadb_x_replay_ctr_t *replext =
4497 4507              (sadb_x_replay_ctr_t *)ksi->ks_in_extv[SADB_X_EXT_REPLAY_VALUE];
4498 4508          sadb_lifetime_t *soft =
4499 4509              (sadb_lifetime_t *)ksi->ks_in_extv[SADB_EXT_LIFETIME_SOFT];
4500 4510          sadb_lifetime_t *hard =
4501 4511              (sadb_lifetime_t *)ksi->ks_in_extv[SADB_EXT_LIFETIME_HARD];
4502 4512          sadb_lifetime_t *idle =
4503 4513              (sadb_lifetime_t *)ksi->ks_in_extv[SADB_X_EXT_LIFETIME_IDLE];
4504 4514          sadb_x_pair_t *pair_ext =
4505 4515              (sadb_x_pair_t *)ksi->ks_in_extv[SADB_X_EXT_PAIR];
4506 4516          ipsa_t *echo_target = NULL;
4507 4517          ipsap_t ipsapp;
4508 4518          ipsa_query_t sq;
4509 4519          time_t current = gethrestime_sec();
4510 4520  
4511 4521          sq.spp = spp;           /* XXX param */
4512 4522          int error = sadb_form_query(ksi, IPSA_Q_SRC|IPSA_Q_DST|IPSA_Q_SA,
4513 4523              IPSA_Q_SRC|IPSA_Q_DST|IPSA_Q_SA|IPSA_Q_INBOUND|IPSA_Q_OUTBOUND|
4514 4524              IPSA_Q_KMC,
4515 4525              &sq, diagnostic);
4516 4526  
4517 4527          if (error != 0)
4518 4528                  return (error);
4519 4529  
4520 4530          error = get_ipsa_pair(&sq, &ipsapp, diagnostic);
4521 4531          if (error != 0)
4522 4532                  return (error);
4523 4533  
4524 4534          if (ipsapp.ipsap_psa_ptr == NULL && ipsapp.ipsap_sa_ptr != NULL) {
4525 4535                  if (ipsapp.ipsap_sa_ptr->ipsa_state == IPSA_STATE_LARVAL) {
4526 4536                          /*
4527 4537                           * REFRELE the target and let the add_sa_func()
4528 4538                           * deal with updating a larval SA.
4529 4539                           */
4530 4540                          destroy_ipsa_pair(&ipsapp);
4531 4541                          return (add_sa_func(mp, ksi, diagnostic, ns));
4532 4542                  }
4533 4543          }
4534 4544  
4535 4545          /*
4536 4546           * At this point we have an UPDATE to a MATURE SA. There should
4537 4547           * not be any keying material present.
4538 4548           */
4539 4549          if (akey != NULL) {
4540 4550                  *diagnostic = SADB_X_DIAGNOSTIC_AKEY_PRESENT;
4541 4551                  error = EINVAL;
4542 4552                  goto bail;
4543 4553          }
4544 4554          if (ekey != NULL) {
4545 4555                  *diagnostic = SADB_X_DIAGNOSTIC_EKEY_PRESENT;
4546 4556                  error = EINVAL;
4547 4557                  goto bail;
4548 4558          }
4549 4559  
4550 4560          if (sq.assoc->sadb_sa_state == SADB_X_SASTATE_ACTIVE_ELSEWHERE) {
4551 4561                  if (ipsapp.ipsap_sa_ptr != NULL &&
4552 4562                      ipsapp.ipsap_sa_ptr->ipsa_state == IPSA_STATE_IDLE) {
4553 4563                          if ((error = sadb_update_state(ipsapp.ipsap_sa_ptr,
4554 4564                              sq.assoc->sadb_sa_state, NULL)) != 0) {
4555 4565                                  *diagnostic = SADB_X_DIAGNOSTIC_BAD_SASTATE;
4556 4566                                  goto bail;
4557 4567                          }
4558 4568                  }
4559 4569                  if (ipsapp.ipsap_psa_ptr != NULL &&
4560 4570                      ipsapp.ipsap_psa_ptr->ipsa_state == IPSA_STATE_IDLE) {
4561 4571                          if ((error = sadb_update_state(ipsapp.ipsap_psa_ptr,
4562 4572                              sq.assoc->sadb_sa_state, NULL)) != 0) {
4563 4573                                  *diagnostic = SADB_X_DIAGNOSTIC_BAD_SASTATE;
4564 4574                                  goto bail;
4565 4575                          }
4566 4576                  }
4567 4577          }
4568 4578          if (sq.assoc->sadb_sa_state == SADB_X_SASTATE_ACTIVE) {
4569 4579                  if (ipsapp.ipsap_sa_ptr != NULL) {
4570 4580                          error = sadb_update_state(ipsapp.ipsap_sa_ptr,
4571 4581                              sq.assoc->sadb_sa_state,
4572 4582                              (ipsapp.ipsap_sa_ptr->ipsa_flags &
4573 4583                              IPSA_F_INBOUND) ? ipkt_lst : NULL);
4574 4584                          if (error) {
4575 4585                                  *diagnostic = SADB_X_DIAGNOSTIC_BAD_SASTATE;
4576 4586                                  goto bail;
4577 4587                          }
4578 4588                  }
4579 4589                  if (ipsapp.ipsap_psa_ptr != NULL) {
4580 4590                          error = sadb_update_state(ipsapp.ipsap_psa_ptr,
4581 4591                              sq.assoc->sadb_sa_state,
4582 4592                              (ipsapp.ipsap_psa_ptr->ipsa_flags &
4583 4593                              IPSA_F_INBOUND) ? ipkt_lst : NULL);
4584 4594                          if (error) {
4585 4595                                  *diagnostic = SADB_X_DIAGNOSTIC_BAD_SASTATE;
4586 4596                                  goto bail;
4587 4597                          }
4588 4598                  }
4589 4599                  sadb_pfkey_echo(pfkey_q, mp, (sadb_msg_t *)mp->b_cont->b_rptr,
4590 4600                      ksi, echo_target);
4591 4601                  goto bail;
4592 4602          }
4593 4603  
4594 4604          /*
4595 4605           * Reality checks for updates of active associations.
4596 4606           * Sundry first-pass UPDATE-specific reality checks.
4597 4607           * Have to do the checks here, because it's after the add_sa code.
4598 4608           * XXX STATS : logging/stats here?
4599 4609           */
4600 4610  
4601 4611          if (!((sq.assoc->sadb_sa_state == SADB_SASTATE_MATURE) ||
4602 4612              (sq.assoc->sadb_sa_state == SADB_X_SASTATE_ACTIVE_ELSEWHERE))) {
4603 4613                  *diagnostic = SADB_X_DIAGNOSTIC_BAD_SASTATE;
4604 4614                  error = EINVAL;
4605 4615                  goto bail;
4606 4616          }
4607 4617          if (sq.assoc->sadb_sa_flags & ~spp->s_updateflags) {
4608 4618                  *diagnostic = SADB_X_DIAGNOSTIC_BAD_SAFLAGS;
4609 4619                  error = EINVAL;
4610 4620                  goto bail;
4611 4621          }
4612 4622          if (ksi->ks_in_extv[SADB_EXT_LIFETIME_CURRENT] != NULL) {
4613 4623                  *diagnostic = SADB_X_DIAGNOSTIC_MISSING_LIFETIME;
4614 4624                  error = EOPNOTSUPP;
4615 4625                  goto bail;
4616 4626          }
4617 4627  
4618 4628          if ((*diagnostic = sadb_hardsoftchk(hard, soft, idle)) != 0) {
4619 4629                  error = EINVAL;
4620 4630                  goto bail;
4621 4631          }
4622 4632  
4623 4633          if ((*diagnostic = sadb_labelchk(ksi)) != 0)
4624 4634                  return (EINVAL);
4625 4635  
4626 4636          error = sadb_check_kmc(&sq, ipsapp.ipsap_sa_ptr, diagnostic);
4627 4637          if (error != 0)
4628 4638                  goto bail;
4629 4639  
4630 4640          error = sadb_check_kmc(&sq, ipsapp.ipsap_psa_ptr, diagnostic);
4631 4641          if (error != 0)
4632 4642                  goto bail;
4633 4643  
4634 4644  
4635 4645          if (ipsapp.ipsap_sa_ptr != NULL) {
4636 4646                  /*
4637 4647                   * Do not allow replay value change for MATURE or LARVAL SA.
4638 4648                   */
4639 4649  
4640 4650                  if ((replext != NULL) &&
4641 4651                      ((ipsapp.ipsap_sa_ptr->ipsa_state == IPSA_STATE_LARVAL) ||
4642 4652                      (ipsapp.ipsap_sa_ptr->ipsa_state == IPSA_STATE_MATURE))) {
4643 4653                          *diagnostic = SADB_X_DIAGNOSTIC_BAD_SASTATE;
4644 4654                          error = EINVAL;
4645 4655                          goto bail;
4646 4656                  }
4647 4657          }
4648 4658  
4649 4659  
4650 4660          if (ipsapp.ipsap_sa_ptr != NULL) {
4651 4661                  sadb_update_lifetimes(ipsapp.ipsap_sa_ptr, hard, soft,
4652 4662                      idle, B_TRUE);
4653 4663                  sadb_update_kmc(&sq, ipsapp.ipsap_sa_ptr);
4654 4664                  if ((replext != NULL) &&
4655 4665                      (ipsapp.ipsap_sa_ptr->ipsa_replay_wsize != 0)) {
4656 4666                          /*
4657 4667                           * If an inbound SA, update the replay counter
4658 4668                           * and check off all the other sequence number
4659 4669                           */
4660 4670                          if (ksi->ks_in_dsttype == KS_IN_ADDR_ME) {
4661 4671                                  if (!sadb_replay_check(ipsapp.ipsap_sa_ptr,
4662 4672                                      replext->sadb_x_rc_replay32)) {
4663 4673                                          *diagnostic =
4664 4674                                              SADB_X_DIAGNOSTIC_INVALID_REPLAY;
4665 4675                                          error = EINVAL;
4666 4676                                          goto bail;
4667 4677                                  }
4668 4678                                  mutex_enter(&ipsapp.ipsap_sa_ptr->ipsa_lock);
4669 4679                                  ipsapp.ipsap_sa_ptr->ipsa_idleexpiretime =
4670 4680                                      current +
4671 4681                                      ipsapp.ipsap_sa_ptr->ipsa_idletime;
4672 4682                                  mutex_exit(&ipsapp.ipsap_sa_ptr->ipsa_lock);
4673 4683                          } else {
4674 4684                                  mutex_enter(&ipsapp.ipsap_sa_ptr->ipsa_lock);
4675 4685                                  ipsapp.ipsap_sa_ptr->ipsa_replay =
4676 4686                                      replext->sadb_x_rc_replay32;
4677 4687                                  ipsapp.ipsap_sa_ptr->ipsa_idleexpiretime =
4678 4688                                      current +
4679 4689                                      ipsapp.ipsap_sa_ptr->ipsa_idletime;
4680 4690                                  mutex_exit(&ipsapp.ipsap_sa_ptr->ipsa_lock);
4681 4691                          }
4682 4692                  }
4683 4693          }
4684 4694  
4685 4695          if (sadb_msg_type == SADB_X_UPDATEPAIR) {
4686 4696                  if (ipsapp.ipsap_psa_ptr != NULL) {
4687 4697                          sadb_update_lifetimes(ipsapp.ipsap_psa_ptr, hard, soft,
4688 4698                              idle, B_FALSE);
4689 4699                          sadb_update_kmc(&sq, ipsapp.ipsap_psa_ptr);
4690 4700                  } else {
4691 4701                          *diagnostic = SADB_X_DIAGNOSTIC_PAIR_SA_NOTFOUND;
4692 4702                          error = ESRCH;
4693 4703                          goto bail;
4694 4704                  }
4695 4705          }
4696 4706  
4697 4707          if (pair_ext != NULL)
4698 4708                  error = update_pairing(&ipsapp, &sq, ksi, diagnostic);
4699 4709  
4700 4710          if (error == 0)
4701 4711                  sadb_pfkey_echo(pfkey_q, mp, (sadb_msg_t *)mp->b_cont->b_rptr,
4702 4712                      ksi, echo_target);
4703 4713  bail:
4704 4714  
4705 4715          destroy_ipsa_pair(&ipsapp);
4706 4716  
4707 4717          return (error);
4708 4718  }
4709 4719  
4710 4720  
4711 4721  static int
4712 4722  update_pairing(ipsap_t *ipsapp, ipsa_query_t *sq, keysock_in_t *ksi,
4713 4723      int *diagnostic)
4714 4724  {
4715 4725          sadb_sa_t *assoc = (sadb_sa_t *)ksi->ks_in_extv[SADB_EXT_SA];
4716 4726          sadb_x_pair_t *pair_ext =
4717 4727              (sadb_x_pair_t *)ksi->ks_in_extv[SADB_X_EXT_PAIR];
4718 4728          int error = 0;
4719 4729          ipsap_t oipsapp;
4720 4730          boolean_t undo_pair = B_FALSE;
4721 4731          uint32_t ipsa_flags;
4722 4732  
4723 4733          if (pair_ext->sadb_x_pair_spi == 0 || pair_ext->sadb_x_pair_spi ==
4724 4734              assoc->sadb_sa_spi) {
4725 4735                  *diagnostic = SADB_X_DIAGNOSTIC_PAIR_INAPPROPRIATE;
4726 4736                  return (EINVAL);
4727 4737          }
4728 4738  
4729 4739          /*
4730 4740           * Assume for now that the spi value provided in the SADB_UPDATE
4731 4741           * message was valid, update the SA with its pair spi value.
4732 4742           * If the spi turns out to be bogus or the SA no longer exists
4733 4743           * then this will be detected when the reverse update is made
4734 4744           * below.
4735 4745           */
4736 4746          mutex_enter(&ipsapp->ipsap_sa_ptr->ipsa_lock);
4737 4747          ipsapp->ipsap_sa_ptr->ipsa_flags |= IPSA_F_PAIRED;
4738 4748          ipsapp->ipsap_sa_ptr->ipsa_otherspi = pair_ext->sadb_x_pair_spi;
4739 4749          mutex_exit(&ipsapp->ipsap_sa_ptr->ipsa_lock);
4740 4750  
4741 4751          /*
4742 4752           * After updating the ipsa_otherspi element of the SA, get_ipsa_pair()
4743 4753           * should now return pointers to the SA *AND* its pair, if this is not
4744 4754           * the case, the "otherspi" either did not exist or was deleted. Also
4745 4755           * check that "otherspi" is not already paired. If everything looks
4746 4756           * good, complete the update. IPSA_REFRELE the first pair_pointer
4747 4757           * after this update to ensure its not deleted until we are done.
4748 4758           */
4749 4759          error = get_ipsa_pair(sq, &oipsapp, diagnostic);
4750 4760          if (error != 0) {
4751 4761                  /*
4752 4762                   * This should never happen, calling function still has
4753 4763                   * IPSA_REFHELD on the SA we just updated.
4754 4764                   */
4755 4765                  return (error); /* XXX EINVAL instead of ESRCH? */
4756 4766          }
4757 4767  
4758 4768          if (oipsapp.ipsap_psa_ptr == NULL) {
4759 4769                  *diagnostic = SADB_X_DIAGNOSTIC_PAIR_INAPPROPRIATE;
4760 4770                  error = EINVAL;
4761 4771                  undo_pair = B_TRUE;
4762 4772          } else {
4763 4773                  ipsa_flags = oipsapp.ipsap_psa_ptr->ipsa_flags;
4764 4774                  if ((oipsapp.ipsap_psa_ptr->ipsa_state == IPSA_STATE_DEAD) ||
4765 4775                      (oipsapp.ipsap_psa_ptr->ipsa_state == IPSA_STATE_DYING)) {
4766 4776                          /* Its dead Jim! */
4767 4777                          *diagnostic = SADB_X_DIAGNOSTIC_PAIR_INAPPROPRIATE;
4768 4778                          undo_pair = B_TRUE;
4769 4779                  } else if ((ipsa_flags & (IPSA_F_OUTBOUND | IPSA_F_INBOUND)) ==
4770 4780                      (IPSA_F_OUTBOUND | IPSA_F_INBOUND)) {
4771 4781                          /* This SA is in both hashtables. */
4772 4782                          *diagnostic = SADB_X_DIAGNOSTIC_PAIR_INAPPROPRIATE;
4773 4783                          undo_pair = B_TRUE;
4774 4784                  } else if (ipsa_flags & IPSA_F_PAIRED) {
4775 4785                          /* This SA is already paired with another. */
4776 4786                          *diagnostic = SADB_X_DIAGNOSTIC_PAIR_ALREADY;
4777 4787                          undo_pair = B_TRUE;
4778 4788                  }
4779 4789          }
4780 4790  
4781 4791          if (undo_pair) {
4782 4792                  /* The pair SA does not exist. */
4783 4793                  mutex_enter(&ipsapp->ipsap_sa_ptr->ipsa_lock);
4784 4794                  ipsapp->ipsap_sa_ptr->ipsa_flags &= ~IPSA_F_PAIRED;
4785 4795                  ipsapp->ipsap_sa_ptr->ipsa_otherspi = 0;
4786 4796                  mutex_exit(&ipsapp->ipsap_sa_ptr->ipsa_lock);
4787 4797          } else {
4788 4798                  mutex_enter(&oipsapp.ipsap_psa_ptr->ipsa_lock);
4789 4799                  oipsapp.ipsap_psa_ptr->ipsa_otherspi = assoc->sadb_sa_spi;
4790 4800                  oipsapp.ipsap_psa_ptr->ipsa_flags |= IPSA_F_PAIRED;
4791 4801                  mutex_exit(&oipsapp.ipsap_psa_ptr->ipsa_lock);
4792 4802          }
4793 4803  
4794 4804          destroy_ipsa_pair(&oipsapp);
4795 4805          return (error);
4796 4806  }
4797 4807  
4798 4808  /*
4799 4809   * The following functions deal with ACQUIRE LISTS.  An ACQUIRE list is
4800 4810   * a list of outstanding SADB_ACQUIRE messages.  If ipsec_getassocbyconn() fails
4801 4811   * for an outbound datagram, that datagram is queued up on an ACQUIRE record,
4802 4812   * and an SADB_ACQUIRE message is sent up.  Presumably, a user-space key
4803 4813   * management daemon will process the ACQUIRE, use a SADB_GETSPI to reserve
4804 4814   * an SPI value and a larval SA, then SADB_UPDATE the larval SA, and ADD the
4805 4815   * other direction's SA.
4806 4816   */
4807 4817  
4808 4818  /*
4809 4819   * Check the ACQUIRE lists.  If there's an existing ACQUIRE record,
4810 4820   * grab it, lock it, and return it.  Otherwise return NULL.
4811 4821   *
4812 4822   * XXX MLS number of arguments getting unwieldy here
4813 4823   */
4814 4824  static ipsacq_t *
4815 4825  sadb_checkacquire(iacqf_t *bucket, ipsec_action_t *ap, ipsec_policy_t *pp,
4816 4826      uint32_t *src, uint32_t *dst, uint32_t *isrc, uint32_t *idst,
4817 4827      uint64_t unique_id, ts_label_t *tsl)
4818 4828  {
4819 4829          ipsacq_t *walker;
4820 4830          sa_family_t fam;
4821 4831          uint32_t blank_address[4] = {0, 0, 0, 0};
4822 4832  
4823 4833          if (isrc == NULL) {
4824 4834                  ASSERT(idst == NULL);
4825 4835                  isrc = idst = blank_address;
4826 4836          }
4827 4837  
4828 4838          /*
4829 4839           * Scan list for duplicates.  Check for UNIQUE, src/dest, policy.
4830 4840           *
4831 4841           * XXX May need search for duplicates based on other things too!
4832 4842           */
4833 4843          for (walker = bucket->iacqf_ipsacq; walker != NULL;
4834 4844              walker = walker->ipsacq_next) {
4835 4845                  mutex_enter(&walker->ipsacq_lock);
4836 4846                  fam = walker->ipsacq_addrfam;
4837 4847                  if (IPSA_ARE_ADDR_EQUAL(dst, walker->ipsacq_dstaddr, fam) &&
4838 4848                      IPSA_ARE_ADDR_EQUAL(src, walker->ipsacq_srcaddr, fam) &&
4839 4849                      ip_addr_match((uint8_t *)isrc, walker->ipsacq_innersrcpfx,
4840 4850                      (in6_addr_t *)walker->ipsacq_innersrc) &&
4841 4851                      ip_addr_match((uint8_t *)idst, walker->ipsacq_innerdstpfx,
4842 4852                      (in6_addr_t *)walker->ipsacq_innerdst) &&
4843 4853                      (ap == walker->ipsacq_act) &&
4844 4854                      (pp == walker->ipsacq_policy) &&
4845 4855                      /* XXX do deep compares of ap/pp? */
4846 4856                      (unique_id == walker->ipsacq_unique_id) &&
4847 4857                      (ipsec_label_match(tsl, walker->ipsacq_tsl)))
4848 4858                          break;                  /* everything matched */
4849 4859                  mutex_exit(&walker->ipsacq_lock);
4850 4860          }
4851 4861  
4852 4862          return (walker);
4853 4863  }
4854 4864  
4855 4865  /*
4856 4866   * Generate an SADB_ACQUIRE base message mblk, including KEYSOCK_OUT metadata.
4857 4867   * In other words, this will return, upon success, a two-mblk chain.
4858 4868   */
4859 4869  static inline mblk_t *
4860 4870  sadb_acquire_msg_base(minor_t serial, uint8_t satype, uint32_t seq, pid_t pid)
4861 4871  {
4862 4872          mblk_t *mp;
4863 4873          sadb_msg_t *samsg;
4864 4874  
4865 4875          mp = sadb_keysock_out(serial);
4866 4876          if (mp == NULL)
4867 4877                  return (NULL);
4868 4878          mp->b_cont = allocb(sizeof (sadb_msg_t), BPRI_HI);
4869 4879          if (mp->b_cont == NULL) {
4870 4880                  freeb(mp);
4871 4881                  return (NULL);
4872 4882          }
4873 4883  
4874 4884          samsg = (sadb_msg_t *)mp->b_cont->b_rptr;
4875 4885          mp->b_cont->b_wptr += sizeof (*samsg);
4876 4886          samsg->sadb_msg_version = PF_KEY_V2;
4877 4887          samsg->sadb_msg_type = SADB_ACQUIRE;
4878 4888          samsg->sadb_msg_errno = 0;
4879 4889          samsg->sadb_msg_reserved = 0;
4880 4890          samsg->sadb_msg_satype = satype;
4881 4891          samsg->sadb_msg_seq = seq;
4882 4892          samsg->sadb_msg_pid = pid;
4883 4893  
4884 4894          return (mp);
4885 4895  }
4886 4896  
4887 4897  /*
4888 4898   * Generate address and TX/MLS sensitivity label PF_KEY extensions that are
4889 4899   * common to both regular and extended ACQUIREs.
4890 4900   */
4891 4901  static mblk_t *
4892 4902  sadb_acquire_msg_common(ipsec_selector_t *sel, ipsec_policy_t *pp,
4893 4903      ipsec_action_t *ap, boolean_t tunnel_mode, ts_label_t *tsl,
4894 4904      sadb_sens_t *sens)
4895 4905  {
4896 4906          size_t len;
4897 4907          mblk_t *mp;
4898 4908          uint8_t *start, *cur, *end;
4899 4909          uint32_t *saddrptr, *daddrptr;
4900 4910          sa_family_t af;
4901 4911          ipsec_action_t *oldap;
4902 4912          ipsec_selkey_t *ipsl;
4903 4913          uint8_t proto, pfxlen;
4904 4914          uint16_t lport, rport;
4905 4915          int senslen = 0;
4906 4916  
4907 4917          /*
4908 4918           * Get action pointer set if it isn't already.
4909 4919           */
4910 4920          oldap = ap;
4911 4921          if (pp != NULL) {
4912 4922                  ap = pp->ipsp_act;
4913 4923                  if (ap == NULL)
4914 4924                          ap = oldap;
4915 4925          }
4916 4926  
4917 4927          /*
4918 4928           * Biggest-case scenario:
4919 4929           * 4x (sadb_address_t + struct sockaddr_in6)
4920 4930           *      (src, dst, isrc, idst)
4921 4931           *      (COMING SOON, 6x, because of triggering-packet contents.)
4922 4932           * sadb_x_kmc_t
4923 4933           * sadb_sens_t
4924 4934           * And wiggle room for label bitvectors.  Luckily there are
4925 4935           * programmatic ways to find it.
4926 4936           */
4927 4937          len = 4 * (sizeof (sadb_address_t) + sizeof (struct sockaddr_in6));
4928 4938  
4929 4939          /* Figure out full and proper length of sensitivity labels. */
4930 4940          if (sens != NULL) {
4931 4941                  ASSERT(tsl == NULL);
4932 4942                  senslen = SADB_64TO8(sens->sadb_sens_len);
4933 4943          } else if (tsl != NULL) {
4934 4944                  senslen = sadb_sens_len_from_label(tsl);
4935 4945          }
4936 4946  #ifdef DEBUG
4937 4947          else {
4938 4948                  ASSERT(senslen == 0);
4939 4949          }
4940 4950  #endif /* DEBUG */
4941 4951          len += senslen;
4942 4952  
4943 4953          mp = allocb(len, BPRI_HI);
4944 4954          if (mp == NULL)
4945 4955                  return (NULL);
4946 4956  
4947 4957          start = mp->b_rptr;
4948 4958          end = start + len;
4949 4959          cur = start;
4950 4960  
4951 4961          /*
4952 4962           * Address extensions first, from most-recently-defined to least.
4953 4963           * (This should immediately trigger surprise or verify robustness on
4954 4964           * older apps, like in.iked.)
4955 4965           */
4956 4966          if (tunnel_mode) {
4957 4967                  /*
4958 4968                   * Form inner address extensions based NOT on the inner
4959 4969                   * selectors (i.e. the packet data), but on the policy's
4960 4970                   * selector key (i.e. the policy's selector information).
4961 4971                   *
4962 4972                   * NOTE:  The position of IPv4 and IPv6 addresses is the
4963 4973                   * same in ipsec_selkey_t (unless the compiler does very
4964 4974                   * strange things with unions, consult your local C language
4965 4975                   * lawyer for details).
4966 4976                   */
4967 4977                  ASSERT(pp != NULL);
4968 4978  
4969 4979                  ipsl = &(pp->ipsp_sel->ipsl_key);
4970 4980                  if (ipsl->ipsl_valid & IPSL_IPV4) {
4971 4981                          af = AF_INET;
4972 4982                          ASSERT(sel->ips_protocol == IPPROTO_ENCAP);
4973 4983                          ASSERT(!(ipsl->ipsl_valid & IPSL_IPV6));
4974 4984                  } else {
4975 4985                          af = AF_INET6;
4976 4986                          ASSERT(sel->ips_protocol == IPPROTO_IPV6);
4977 4987                          ASSERT(ipsl->ipsl_valid & IPSL_IPV6);
4978 4988                  }
4979 4989  
4980 4990                  if (ipsl->ipsl_valid & IPSL_LOCAL_ADDR) {
4981 4991                          saddrptr = (uint32_t *)(&ipsl->ipsl_local);
4982 4992                          pfxlen = ipsl->ipsl_local_pfxlen;
4983 4993                  } else {
4984 4994                          saddrptr = (uint32_t *)(&ipv6_all_zeros);
4985 4995                          pfxlen = 0;
4986 4996                  }
4987 4997                  /* XXX What about ICMP type/code? */
4988 4998                  lport = (ipsl->ipsl_valid & IPSL_LOCAL_PORT) ?
4989 4999                      ipsl->ipsl_lport : 0;
4990 5000                  proto = (ipsl->ipsl_valid & IPSL_PROTOCOL) ?
4991 5001                      ipsl->ipsl_proto : 0;
4992 5002  
4993 5003                  cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_SRC,
4994 5004                      af, saddrptr, lport, proto, pfxlen);
4995 5005                  if (cur == NULL) {
4996 5006                          freeb(mp);
4997 5007                          return (NULL);
4998 5008                  }
4999 5009  
5000 5010                  if (ipsl->ipsl_valid & IPSL_REMOTE_ADDR) {
5001 5011                          daddrptr = (uint32_t *)(&ipsl->ipsl_remote);
5002 5012                          pfxlen = ipsl->ipsl_remote_pfxlen;
5003 5013                  } else {
5004 5014                          daddrptr = (uint32_t *)(&ipv6_all_zeros);
5005 5015                          pfxlen = 0;
5006 5016                  }
5007 5017                  /* XXX What about ICMP type/code? */
5008 5018                  rport = (ipsl->ipsl_valid & IPSL_REMOTE_PORT) ?
5009 5019                      ipsl->ipsl_rport : 0;
5010 5020  
5011 5021                  cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_DST,
5012 5022                      af, daddrptr, rport, proto, pfxlen);
5013 5023                  if (cur == NULL) {
5014 5024                          freeb(mp);
5015 5025                          return (NULL);
5016 5026                  }
5017 5027                  /*
5018 5028                   * TODO  - if we go to 3884's dream of transport mode IP-in-IP
5019 5029                   * _with_ inner-packet address selectors, we'll need to further
5020 5030                   * distinguish tunnel mode here.  For now, having inner
5021 5031                   * addresses and/or ports is sufficient.
5022 5032                   *
5023 5033                   * Meanwhile, whack proto/ports to reflect IP-in-IP for the
5024 5034                   * outer addresses.
5025 5035                   */
5026 5036                  proto = sel->ips_protocol;      /* Either _ENCAP or _IPV6 */
5027 5037                  lport = rport = 0;
5028 5038          } else if ((ap != NULL) && (!ap->ipa_want_unique)) {
5029 5039                  /*
5030 5040                   * For cases when the policy calls out specific ports (or not).
5031 5041                   */
5032 5042                  proto = 0;
5033 5043                  lport = 0;
5034 5044                  rport = 0;
5035 5045                  if (pp != NULL) {
5036 5046                          ipsl = &(pp->ipsp_sel->ipsl_key);
5037 5047                          if (ipsl->ipsl_valid & IPSL_PROTOCOL)
5038 5048                                  proto = ipsl->ipsl_proto;
5039 5049                          if (ipsl->ipsl_valid & IPSL_REMOTE_PORT)
5040 5050                                  rport = ipsl->ipsl_rport;
5041 5051                          if (ipsl->ipsl_valid & IPSL_LOCAL_PORT)
5042 5052                                  lport = ipsl->ipsl_lport;
5043 5053                  }
5044 5054          } else {
5045 5055                  /*
5046 5056                   * For require-unique-SA policies.
5047 5057                   */
5048 5058                  proto = sel->ips_protocol;
5049 5059                  lport = sel->ips_local_port;
5050 5060                  rport = sel->ips_remote_port;
5051 5061          }
5052 5062  
5053 5063          /*
5054 5064           * Regular addresses.  These are outer-packet ones for tunnel mode.
5055 5065           * Or for transport mode, the regulard address & port information.
5056 5066           */
5057 5067          af = sel->ips_isv4 ? AF_INET : AF_INET6;
5058 5068  
5059 5069          /*
5060 5070           * NOTE:  The position of IPv4 and IPv6 addresses is the same in
5061 5071           * ipsec_selector_t.
5062 5072           */
5063 5073          cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_SRC, af,
5064 5074              (uint32_t *)(&sel->ips_local_addr_v6), lport, proto, 0);
5065 5075          if (cur == NULL) {
5066 5076                  freeb(mp);
5067 5077                  return (NULL);
5068 5078          }
5069 5079  
5070 5080          cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_DST, af,
5071 5081              (uint32_t *)(&sel->ips_remote_addr_v6), rport, proto, 0);
5072 5082          if (cur == NULL) {
5073 5083                  freeb(mp);
5074 5084                  return (NULL);
5075 5085          }
5076 5086  
5077 5087          /*
5078 5088           * If present, generate a sensitivity label.
5079 5089           */
5080 5090          if (cur + senslen > end) {
5081 5091                  freeb(mp);
5082 5092                  return (NULL);
5083 5093          }
5084 5094          if (sens != NULL) {
5085 5095                  /* Explicit sadb_sens_t, usually from inverse-ACQUIRE. */
5086 5096                  bcopy(sens, cur, senslen);
5087 5097          } else if (tsl != NULL) {
5088 5098                  /* Generate sadb_sens_t from ACQUIRE source. */
5089 5099                  sadb_sens_from_label((sadb_sens_t *)cur, SADB_EXT_SENSITIVITY,
5090 5100                      tsl, senslen);
5091 5101          }
5092 5102  #ifdef DEBUG
5093 5103          else {
5094 5104                  ASSERT(senslen == 0);
5095 5105          }
5096 5106  #endif /* DEBUG */
5097 5107          cur += senslen;
5098 5108          mp->b_wptr = cur;
5099 5109  
5100 5110          return (mp);
5101 5111  }
5102 5112  
5103 5113  /*
5104 5114   * Generate a regular ACQUIRE's proposal extension and KMC information..
5105 5115   */
5106 5116  static mblk_t *
5107 5117  sadb_acquire_prop(ipsec_action_t *ap, netstack_t *ns, boolean_t do_esp)
5108 5118  {
5109 5119          ipsec_stack_t *ipss = ns->netstack_ipsec;
5110 5120          ipsecesp_stack_t *espstack = ns->netstack_ipsecesp;
5111 5121          ipsecah_stack_t *ahstack = ns->netstack_ipsecah;
5112 5122          mblk_t *mp = NULL;
5113 5123          sadb_prop_t *prop;
5114 5124          sadb_comb_t *comb;
5115 5125          ipsec_action_t *walker;
5116 5126          int ncombs, allocsize, ealgid, aalgid, aminbits, amaxbits, eminbits,
5117 5127              emaxbits, replay;
5118 5128          uint64_t softbytes, hardbytes, softaddtime, hardaddtime, softusetime,
5119 5129              hardusetime;
5120 5130          uint64_t kmc = 0;
5121 5131          uint32_t kmp = 0;
5122 5132  
5123 5133          /*
5124 5134           * Since it's an rwlock read, AND writing to the IPsec algorithms is
5125 5135           * rare, just acquire it once up top, and drop it upon return.
5126 5136           */
5127 5137          rw_enter(&ipss->ipsec_alg_lock, RW_READER);
5128 5138          if (do_esp) {
5129 5139                  uint64_t num_aalgs, num_ealgs;
5130 5140  
5131 5141                  if (espstack->esp_kstats == NULL)
5132 5142                          goto bail;
5133 5143  
5134 5144                  num_aalgs = ipss->ipsec_nalgs[IPSEC_ALG_AUTH];
5135 5145                  num_ealgs = ipss->ipsec_nalgs[IPSEC_ALG_ENCR];
5136 5146                  if (num_ealgs == 0)
5137 5147                          goto bail;      /* IPsec not loaded yet, apparently. */
5138 5148                  num_aalgs++;    /* No-auth or self-auth-crypto ESP. */
5139 5149  
5140 5150                  /* Use netstack's maximum loaded algorithms... */
5141 5151                  ncombs = num_ealgs * num_aalgs;
5142 5152                  replay =  espstack->ipsecesp_replay_size;
5143 5153          } else {
5144 5154                  if (ahstack->ah_kstats == NULL)
5145 5155                          goto bail;
5146 5156  
5147 5157                  ncombs = ipss->ipsec_nalgs[IPSEC_ALG_AUTH];
5148 5158  
5149 5159                  if (ncombs == 0)
5150 5160                          goto bail;      /* IPsec not loaded yet, apparently. */
5151 5161                  replay =  ahstack->ipsecah_replay_size;
5152 5162          }
5153 5163  
5154 5164          allocsize = sizeof (*prop) + ncombs * sizeof (*comb) +
5155 5165              sizeof (sadb_x_kmc_t);
5156 5166          mp = allocb(allocsize, BPRI_HI);
5157 5167          if (mp == NULL)
5158 5168                  goto bail;
5159 5169          prop = (sadb_prop_t *)mp->b_rptr;
5160 5170          mp->b_wptr += sizeof (*prop);
5161 5171          comb = (sadb_comb_t *)mp->b_wptr;
5162 5172          /* Decrement allocsize, if it goes to or below 0, stop. */
5163 5173          allocsize -= sizeof (*prop);
5164 5174          prop->sadb_prop_exttype = SADB_EXT_PROPOSAL;
5165 5175          prop->sadb_prop_len = SADB_8TO64(sizeof (*prop));
5166 5176          *(uint32_t *)(&prop->sadb_prop_replay) = 0;     /* Quick zero-out! */
5167 5177          prop->sadb_prop_replay = replay;
5168 5178  
5169 5179          /*
5170 5180           * Based upon algorithm properties, and what-not, prioritize a
5171 5181           * proposal, based on the ordering of the ESP algorithms in the
5172 5182           * alternatives in the policy rule or socket that was placed
5173 5183           * in the acquire record.
5174 5184           *
5175 5185           * For each action in policy list
5176 5186           *   Add combination.
5177 5187           *   I should not hit it, but if I've hit limit, return.
5178 5188           */
5179 5189  
5180 5190          for (walker = ap; walker != NULL; walker = walker->ipa_next) {
5181 5191                  ipsec_alginfo_t *ealg, *aalg;
5182 5192                  ipsec_prot_t *prot;
5183 5193  
5184 5194                  if (walker->ipa_act.ipa_type != IPSEC_POLICY_APPLY)
5185 5195                          continue;
5186 5196  
5187 5197                  prot = &walker->ipa_act.ipa_apply;
5188 5198                  if (walker->ipa_act.ipa_apply.ipp_km_proto != 0)
5189 5199                          kmp = walker->ipa_act.ipa_apply.ipp_km_proto;
5190 5200                  if (walker->ipa_act.ipa_apply.ipp_km_cookie != 0)
5191 5201                          kmc = walker->ipa_act.ipa_apply.ipp_km_cookie;
5192 5202                  if (walker->ipa_act.ipa_apply.ipp_replay_depth) {
5193 5203                          prop->sadb_prop_replay =
5194 5204                              walker->ipa_act.ipa_apply.ipp_replay_depth;
5195 5205                  }
5196 5206  
5197 5207                  if (do_esp) {
5198 5208                          if (!prot->ipp_use_esp)
5199 5209                                  continue;
5200 5210  
5201 5211                          if (prot->ipp_esp_auth_alg != 0) {
5202 5212                                  aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH]
5203 5213                                      [prot->ipp_esp_auth_alg];
5204 5214                                  if (aalg == NULL || !ALG_VALID(aalg))
5205 5215                                          continue;
5206 5216                          } else
5207 5217                                  aalg = NULL;
5208 5218  
5209 5219                          ASSERT(prot->ipp_encr_alg > 0);
5210 5220                          ealg = ipss->ipsec_alglists[IPSEC_ALG_ENCR]
5211 5221                              [prot->ipp_encr_alg];
5212 5222                          if (ealg == NULL || !ALG_VALID(ealg))
5213 5223                                  continue;
5214 5224  
5215 5225                          /*
5216 5226                           * These may want to come from policy rule..
5217 5227                           */
5218 5228                          softbytes = espstack->ipsecesp_default_soft_bytes;
5219 5229                          hardbytes = espstack->ipsecesp_default_hard_bytes;
5220 5230                          softaddtime = espstack->ipsecesp_default_soft_addtime;
5221 5231                          hardaddtime = espstack->ipsecesp_default_hard_addtime;
5222 5232                          softusetime = espstack->ipsecesp_default_soft_usetime;
5223 5233                          hardusetime = espstack->ipsecesp_default_hard_usetime;
5224 5234                  } else {
5225 5235                          if (!prot->ipp_use_ah)
5226 5236                                  continue;
5227 5237                          ealg = NULL;
5228 5238                          aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH]
5229 5239                              [prot->ipp_auth_alg];
5230 5240                          if (aalg == NULL || !ALG_VALID(aalg))
5231 5241                                  continue;
5232 5242  
5233 5243                          /*
5234 5244                           * These may want to come from policy rule..
5235 5245                           */
5236 5246                          softbytes = ahstack->ipsecah_default_soft_bytes;
5237 5247                          hardbytes = ahstack->ipsecah_default_hard_bytes;
5238 5248                          softaddtime = ahstack->ipsecah_default_soft_addtime;
5239 5249                          hardaddtime = ahstack->ipsecah_default_hard_addtime;
5240 5250                          softusetime = ahstack->ipsecah_default_soft_usetime;
5241 5251                          hardusetime = ahstack->ipsecah_default_hard_usetime;
5242 5252                  }
5243 5253  
5244 5254                  if (ealg == NULL) {
5245 5255                          ealgid = eminbits = emaxbits = 0;
5246 5256                  } else {
5247 5257                          ealgid = ealg->alg_id;
5248 5258                          eminbits =
5249 5259                              MAX(prot->ipp_espe_minbits, ealg->alg_ef_minbits);
5250 5260                          emaxbits =
5251 5261                              MIN(prot->ipp_espe_maxbits, ealg->alg_ef_maxbits);
5252 5262                  }
5253 5263  
5254 5264                  if (aalg == NULL) {
5255 5265                          aalgid = aminbits = amaxbits = 0;
5256 5266                  } else {
5257 5267                          aalgid = aalg->alg_id;
5258 5268                          aminbits = MAX(prot->ipp_espa_minbits,
5259 5269                              aalg->alg_ef_minbits);
5260 5270                          amaxbits = MIN(prot->ipp_espa_maxbits,
5261 5271                              aalg->alg_ef_maxbits);
5262 5272                  }
5263 5273  
5264 5274                  comb->sadb_comb_flags = 0;
5265 5275                  comb->sadb_comb_reserved = 0;
5266 5276                  comb->sadb_comb_encrypt = ealgid;
5267 5277                  comb->sadb_comb_encrypt_minbits = eminbits;
5268 5278                  comb->sadb_comb_encrypt_maxbits = emaxbits;
5269 5279                  comb->sadb_comb_auth = aalgid;
5270 5280                  comb->sadb_comb_auth_minbits = aminbits;
5271 5281                  comb->sadb_comb_auth_maxbits = amaxbits;
5272 5282                  comb->sadb_comb_soft_allocations = 0;
5273 5283                  comb->sadb_comb_hard_allocations = 0;
5274 5284                  comb->sadb_comb_soft_bytes = softbytes;
5275 5285                  comb->sadb_comb_hard_bytes = hardbytes;
5276 5286                  comb->sadb_comb_soft_addtime = softaddtime;
5277 5287                  comb->sadb_comb_hard_addtime = hardaddtime;
5278 5288                  comb->sadb_comb_soft_usetime = softusetime;
5279 5289                  comb->sadb_comb_hard_usetime = hardusetime;
5280 5290  
5281 5291                  prop->sadb_prop_len += SADB_8TO64(sizeof (*comb));
5282 5292                  mp->b_wptr += sizeof (*comb);
5283 5293                  allocsize -= sizeof (*comb);
5284 5294                  /* Should never dip BELOW sizeof (KM cookie extension). */
5285 5295                  ASSERT3S(allocsize, >=, sizeof (sadb_x_kmc_t));
5286 5296                  if (allocsize <= sizeof (sadb_x_kmc_t))
5287 5297                          break;  /* out of space.. */
5288 5298                  comb++;
5289 5299          }
5290 5300  
5291 5301          /* Don't include KMC extension if there's no room. */
5292 5302          if (((kmp != 0) || (kmc != 0)) && allocsize >= sizeof (sadb_x_kmc_t)) {
5293 5303                  if (sadb_make_kmc_ext(mp->b_wptr,
5294 5304                      mp->b_wptr + sizeof (sadb_x_kmc_t), kmp, kmc) == NULL) {
5295 5305                          freeb(mp);
5296 5306                          mp = NULL;
5297 5307                          goto bail;
5298 5308                  }
5299 5309                  mp->b_wptr += sizeof (sadb_x_kmc_t);
5300 5310                  prop->sadb_prop_len += SADB_8TO64(sizeof (sadb_x_kmc_t));
5301 5311          }
5302 5312  
5303 5313  bail:
5304 5314          rw_exit(&ipss->ipsec_alg_lock);
5305 5315          return (mp);
5306 5316  }
5307 5317  
5308 5318  /*
5309 5319   * Generate an extended ACQUIRE's extended-proposal extension.
5310 5320   */
5311 5321  static mblk_t *
5312 5322  sadb_acquire_extended_prop(ipsec_action_t *ap, netstack_t *ns)
5313 5323  {
5314 5324          sadb_prop_t *eprop;
5315 5325          uint8_t *cur, *end;
5316 5326          mblk_t *mp;
5317 5327          int allocsize, numecombs = 0, numalgdescs = 0;
5318 5328          uint32_t kmp = 0, replay = 0;
5319 5329          uint64_t kmc = 0;
5320 5330          ipsec_action_t *walker;
5321 5331  
5322 5332          allocsize = sizeof (*eprop);
5323 5333  
5324 5334          /*
5325 5335           * Going to walk through the action list twice.  Once for allocation
5326 5336           * measurement, and once for actual construction.
5327 5337           */
5328 5338          for (walker = ap; walker != NULL; walker = walker->ipa_next) {
5329 5339                  ipsec_prot_t *ipp;
5330 5340  
5331 5341                  /*
5332 5342                   * Skip non-IPsec policies
5333 5343                   */
5334 5344                  if (walker->ipa_act.ipa_type != IPSEC_ACT_APPLY)
5335 5345                          continue;
5336 5346  
5337 5347                  ipp = &walker->ipa_act.ipa_apply;
5338 5348  
5339 5349                  if (walker->ipa_act.ipa_apply.ipp_km_proto)
5340 5350                          kmp = ipp->ipp_km_proto;
5341 5351                  if (walker->ipa_act.ipa_apply.ipp_km_cookie)
5342 5352                          kmc = ipp->ipp_km_cookie;
5343 5353                  if (walker->ipa_act.ipa_apply.ipp_replay_depth)
5344 5354                          replay = ipp->ipp_replay_depth;
5345 5355  
5346 5356                  if (ipp->ipp_use_ah)
5347 5357                          numalgdescs++;
5348 5358                  if (ipp->ipp_use_esp) {
5349 5359                          numalgdescs++;
5350 5360                          if (ipp->ipp_use_espa)
5351 5361                                  numalgdescs++;
5352 5362                  }
5353 5363  
5354 5364                  numecombs++;
5355 5365          }
5356 5366          ASSERT(numecombs > 0);
5357 5367  
5358 5368          allocsize += numecombs * sizeof (sadb_x_ecomb_t) +
5359 5369              numalgdescs * sizeof (sadb_x_algdesc_t) + sizeof (sadb_x_kmc_t);
5360 5370          mp = allocb(allocsize, BPRI_HI);
5361 5371          if (mp == NULL)
5362 5372                  return (NULL);
5363 5373          eprop = (sadb_prop_t *)mp->b_rptr;
5364 5374          end = mp->b_rptr + allocsize;
5365 5375          cur = mp->b_rptr + sizeof (*eprop);
5366 5376  
5367 5377          eprop->sadb_prop_exttype = SADB_X_EXT_EPROP;
5368 5378          eprop->sadb_x_prop_ereserved = 0;
5369 5379          eprop->sadb_x_prop_numecombs = 0;
5370 5380          *(uint32_t *)(&eprop->sadb_prop_replay) = 0;    /* Quick zero-out! */
5371 5381          /* Pick ESP's replay default if need be. */
5372 5382          eprop->sadb_prop_replay = (replay == 0) ?
5373 5383              ns->netstack_ipsecesp->ipsecesp_replay_size : replay;
5374 5384  
5375 5385          /* This time, walk through and actually allocate. */
5376 5386          for (walker = ap; walker != NULL; walker = walker->ipa_next) {
5377 5387                  /*
5378 5388                   * Skip non-IPsec policies
5379 5389                   */
5380 5390                  if (walker->ipa_act.ipa_type != IPSEC_ACT_APPLY)
5381 5391                          continue;
5382 5392                  cur = sadb_action_to_ecomb(cur, end, walker, ns);
5383 5393                  if (cur == NULL) {
5384 5394                          /* NOTE: inverse-ACQUIRE should note this as ENOMEM. */
5385 5395                          freeb(mp);
5386 5396                          return (NULL);
5387 5397                  }
5388 5398                  eprop->sadb_x_prop_numecombs++;
5389 5399          }
5390 5400  
5391 5401          ASSERT(end - cur >= sizeof (sadb_x_kmc_t));
5392 5402          if ((kmp != 0) || (kmc != 0)) {
5393 5403                  cur = sadb_make_kmc_ext(cur, end, kmp, kmc);
5394 5404                  if (cur == NULL) {
5395 5405                          freeb(mp);
5396 5406                          return (NULL);
5397 5407                  }
5398 5408          }
5399 5409          mp->b_wptr = cur;
5400 5410          eprop->sadb_prop_len = SADB_8TO64(cur - mp->b_rptr);
5401 5411  
5402 5412          return (mp);
5403 5413  }
5404 5414  
5405 5415  /*
5406 5416   * For this mblk, insert a new acquire record.  Assume bucket contains addrs
5407 5417   * of all of the same length.  Give up (and drop) if memory
5408 5418   * cannot be allocated for a new one; otherwise, invoke callback to
5409 5419   * send the acquire up..
5410 5420   *
5411 5421   * In cases where we need both AH and ESP, add the SA to the ESP ACQUIRE
5412 5422   * list.  The ah_add_sa_finish() routines can look at the packet's attached
5413 5423   * attributes and handle this case specially.
5414 5424   */
5415 5425  void
5416 5426  sadb_acquire(mblk_t *datamp, ip_xmit_attr_t *ixa, boolean_t need_ah,
5417 5427      boolean_t need_esp)
5418 5428  {
5419 5429          mblk_t  *asyncmp, *regular, *extended, *common, *prop, *eprop;
5420 5430          sadbp_t *spp;
5421 5431          sadb_t *sp;
5422 5432          ipsacq_t *newbie;
5423 5433          iacqf_t *bucket;
5424 5434          ipha_t *ipha = (ipha_t *)datamp->b_rptr;
5425 5435          ip6_t *ip6h = (ip6_t *)datamp->b_rptr;
5426 5436          uint32_t *src, *dst, *isrc, *idst;
5427 5437          ipsec_policy_t *pp = ixa->ixa_ipsec_policy;
5428 5438          ipsec_action_t *ap = ixa->ixa_ipsec_action;
5429 5439          sa_family_t af;
5430 5440          int hashoffset;
5431 5441          uint32_t seq;
5432 5442          uint64_t unique_id = 0;
5433 5443          boolean_t tunnel_mode = (ixa->ixa_flags & IXAF_IPSEC_TUNNEL) != 0;
5434 5444          ts_label_t      *tsl;
5435 5445          netstack_t      *ns = ixa->ixa_ipst->ips_netstack;
5436 5446          ipsec_stack_t   *ipss = ns->netstack_ipsec;
5437 5447          ipsecesp_stack_t *espstack = ns->netstack_ipsecesp;
5438 5448          ipsecah_stack_t *ahstack = ns->netstack_ipsecah;
5439 5449          ipsec_selector_t sel;
5440 5450          queue_t *q;
5441 5451  
5442 5452          ASSERT((pp != NULL) || (ap != NULL));
5443 5453  
5444 5454          ASSERT(need_ah || need_esp);
5445 5455  
5446 5456          /* Assign sadb pointers */
5447 5457          if (need_esp) {
5448 5458                  /*
5449 5459                   * ESP happens first if we need both AH and ESP.
5450 5460                   */
5451 5461                  spp = &espstack->esp_sadb;
5452 5462          } else {
5453 5463                  spp = &ahstack->ah_sadb;
5454 5464          }
5455 5465          sp = (ixa->ixa_flags & IXAF_IS_IPV4) ? &spp->s_v4 : &spp->s_v6;
5456 5466  
5457 5467          if (is_system_labeled())
5458 5468                  tsl = ixa->ixa_tsl;
5459 5469          else
5460 5470                  tsl = NULL;
5461 5471  
5462 5472          if (ap == NULL)
5463 5473                  ap = pp->ipsp_act;
5464 5474          ASSERT(ap != NULL);
5465 5475  
5466 5476          if (ap->ipa_act.ipa_apply.ipp_use_unique || tunnel_mode)
5467 5477                  unique_id = SA_FORM_UNIQUE_ID(ixa);
5468 5478  
5469 5479          /*
5470 5480           * Set up an ACQUIRE record.
5471 5481           *
5472 5482           * Immediately, make sure the ACQUIRE sequence number doesn't slip
5473 5483           * below the lowest point allowed in the kernel.  (In other words,
5474 5484           * make sure the high bit on the sequence number is set.)
5475 5485           */
5476 5486  
5477 5487          seq = keysock_next_seq(ns) | IACQF_LOWEST_SEQ;
5478 5488  
5479 5489          if (IPH_HDR_VERSION(ipha) == IP_VERSION) {
5480 5490                  src = (uint32_t *)&ipha->ipha_src;
5481 5491                  dst = (uint32_t *)&ipha->ipha_dst;
5482 5492                  af = AF_INET;
5483 5493                  hashoffset = OUTBOUND_HASH_V4(sp, ipha->ipha_dst);
5484 5494                  ASSERT(ixa->ixa_flags & IXAF_IS_IPV4);
5485 5495          } else {
5486 5496                  ASSERT(IPH_HDR_VERSION(ipha) == IPV6_VERSION);
5487 5497                  src = (uint32_t *)&ip6h->ip6_src;
5488 5498                  dst = (uint32_t *)&ip6h->ip6_dst;
5489 5499                  af = AF_INET6;
5490 5500                  hashoffset = OUTBOUND_HASH_V6(sp, ip6h->ip6_dst);
5491 5501                  ASSERT(!(ixa->ixa_flags & IXAF_IS_IPV4));
5492 5502          }
5493 5503  
5494 5504          if (tunnel_mode) {
5495 5505                  if (pp == NULL) {
5496 5506                          /*
5497 5507                           * Tunnel mode with no policy pointer means this is a
5498 5508                           * reflected ICMP (like a ECHO REQUEST) that came in
5499 5509                           * with self-encapsulated protection.  Until we better
5500 5510                           * support this, drop the packet.
5501 5511                           */
5502 5512                          ip_drop_packet(datamp, B_FALSE, NULL,
5503 5513                              DROPPER(ipss, ipds_spd_got_selfencap),
5504 5514                              &ipss->ipsec_spd_dropper);
5505 5515                          return;
5506 5516                  }
5507 5517                  /* Snag inner addresses. */
5508 5518                  isrc = ixa->ixa_ipsec_insrc;
5509 5519                  idst = ixa->ixa_ipsec_indst;
5510 5520          } else {
5511 5521                  isrc = idst = NULL;
5512 5522          }
5513 5523  
5514 5524          /*
5515 5525           * Check buckets to see if there is an existing entry.  If so,
5516 5526           * grab it.  sadb_checkacquire locks newbie if found.
5517 5527           */
5518 5528          bucket = &(sp->sdb_acq[hashoffset]);
5519 5529          mutex_enter(&bucket->iacqf_lock);
5520 5530          newbie = sadb_checkacquire(bucket, ap, pp, src, dst, isrc, idst,
5521 5531              unique_id, tsl);
5522 5532  
5523 5533          if (newbie == NULL) {
5524 5534                  /*
5525 5535                   * Otherwise, allocate a new one.
5526 5536                   */
5527 5537                  newbie = kmem_zalloc(sizeof (*newbie), KM_NOSLEEP);
5528 5538                  if (newbie == NULL) {
5529 5539                          mutex_exit(&bucket->iacqf_lock);
5530 5540                          ip_drop_packet(datamp, B_FALSE, NULL,
5531 5541                              DROPPER(ipss, ipds_sadb_acquire_nomem),
5532 5542                              &ipss->ipsec_sadb_dropper);
5533 5543                          return;
5534 5544                  }
5535 5545                  newbie->ipsacq_policy = pp;
5536 5546                  if (pp != NULL) {
5537 5547                          IPPOL_REFHOLD(pp);
5538 5548                  }
5539 5549                  IPACT_REFHOLD(ap);
5540 5550                  newbie->ipsacq_act = ap;
5541 5551                  newbie->ipsacq_linklock = &bucket->iacqf_lock;
5542 5552                  newbie->ipsacq_next = bucket->iacqf_ipsacq;
5543 5553                  newbie->ipsacq_ptpn = &bucket->iacqf_ipsacq;
5544 5554                  if (newbie->ipsacq_next != NULL)
5545 5555                          newbie->ipsacq_next->ipsacq_ptpn = &newbie->ipsacq_next;
5546 5556  
5547 5557                  bucket->iacqf_ipsacq = newbie;
5548 5558                  mutex_init(&newbie->ipsacq_lock, NULL, MUTEX_DEFAULT, NULL);
5549 5559                  mutex_enter(&newbie->ipsacq_lock);
5550 5560          }
5551 5561  
5552 5562          /*
5553 5563           * XXX MLS does it actually help us to drop the bucket lock here?
5554 5564           * we have inserted a half-built, locked acquire record into the
5555 5565           * bucket.  any competing thread will now be able to lock the bucket
5556 5566           * to scan it, but will immediately pile up on the new acquire
5557 5567           * record's lock; I don't think we gain anything here other than to
5558 5568           * disperse blame for lock contention.
5559 5569           *
5560 5570           * we might be able to dispense with acquire record locks entirely..
5561 5571           * just use the bucket locks..
5562 5572           */
5563 5573  
5564 5574          mutex_exit(&bucket->iacqf_lock);
5565 5575  
5566 5576          /*
5567 5577           * This assert looks silly for now, but we may need to enter newbie's
5568 5578           * mutex during a search.
5569 5579           */
5570 5580          ASSERT(MUTEX_HELD(&newbie->ipsacq_lock));
5571 5581  
5572 5582          /*
5573 5583           * Make the ip_xmit_attr_t into something we can queue.
5574 5584           * If no memory it frees datamp.
5575 5585           */
5576 5586          asyncmp = ip_xmit_attr_to_mblk(ixa);
5577 5587          if (asyncmp != NULL)
5578 5588                  linkb(asyncmp, datamp);
5579 5589  
5580 5590          /* Queue up packet.  Use b_next. */
5581 5591  
5582 5592          if (asyncmp == NULL) {
5583 5593                  /* Statistics for allocation failure */
5584 5594                  if (ixa->ixa_flags & IXAF_IS_IPV4) {
5585 5595                          BUMP_MIB(&ixa->ixa_ipst->ips_ip_mib,
5586 5596                              ipIfStatsOutDiscards);
5587 5597                  } else {
5588 5598                          BUMP_MIB(&ixa->ixa_ipst->ips_ip6_mib,
5589 5599                              ipIfStatsOutDiscards);
5590 5600                  }
5591 5601                  ip_drop_output("No memory for asyncmp", datamp, NULL);
5592 5602                  freemsg(datamp);
5593 5603                  /*
5594 5604                   * The acquire record will be freed quickly if it's new
5595 5605                   * (ipsacq_expire == 0), and will proceed as if no packet
5596 5606                   * showed up if not.
5597 5607                   */
5598 5608                  mutex_exit(&newbie->ipsacq_lock);
5599 5609                  return;
5600 5610          } else if (newbie->ipsacq_numpackets == 0) {
5601 5611                  /* First one. */
5602 5612                  newbie->ipsacq_mp = asyncmp;
5603 5613                  newbie->ipsacq_numpackets = 1;
5604 5614                  newbie->ipsacq_expire = gethrestime_sec();
5605 5615                  /*
5606 5616                   * Extended ACQUIRE with both AH+ESP will use ESP's timeout
5607 5617                   * value.
5608 5618                   */
5609 5619                  newbie->ipsacq_expire += *spp->s_acquire_timeout;
5610 5620                  newbie->ipsacq_seq = seq;
5611 5621                  newbie->ipsacq_addrfam = af;
5612 5622  
5613 5623                  newbie->ipsacq_srcport = ixa->ixa_ipsec_src_port;
5614 5624                  newbie->ipsacq_dstport = ixa->ixa_ipsec_dst_port;
5615 5625                  newbie->ipsacq_icmp_type = ixa->ixa_ipsec_icmp_type;
5616 5626                  newbie->ipsacq_icmp_code = ixa->ixa_ipsec_icmp_code;
5617 5627                  if (tunnel_mode) {
5618 5628                          newbie->ipsacq_inneraddrfam = ixa->ixa_ipsec_inaf;
5619 5629                          newbie->ipsacq_proto = ixa->ixa_ipsec_inaf == AF_INET6 ?
5620 5630                              IPPROTO_IPV6 : IPPROTO_ENCAP;
5621 5631                          newbie->ipsacq_innersrcpfx = ixa->ixa_ipsec_insrcpfx;
5622 5632                          newbie->ipsacq_innerdstpfx = ixa->ixa_ipsec_indstpfx;
5623 5633                          IPSA_COPY_ADDR(newbie->ipsacq_innersrc,
5624 5634                              ixa->ixa_ipsec_insrc, ixa->ixa_ipsec_inaf);
5625 5635                          IPSA_COPY_ADDR(newbie->ipsacq_innerdst,
5626 5636                              ixa->ixa_ipsec_indst, ixa->ixa_ipsec_inaf);
5627 5637                  } else {
5628 5638                          newbie->ipsacq_proto = ixa->ixa_ipsec_proto;
5629 5639                  }
5630 5640                  newbie->ipsacq_unique_id = unique_id;
5631 5641  
5632 5642                  if (tsl != NULL) {
5633 5643                          label_hold(tsl);
5634 5644                          newbie->ipsacq_tsl = tsl;
5635 5645                  }
5636 5646          } else {
5637 5647                  /* Scan to the end of the list & insert. */
5638 5648                  mblk_t *lastone = newbie->ipsacq_mp;
5639 5649  
5640 5650                  while (lastone->b_next != NULL)
5641 5651                          lastone = lastone->b_next;
5642 5652                  lastone->b_next = asyncmp;
5643 5653                  if (newbie->ipsacq_numpackets++ == ipsacq_maxpackets) {
5644 5654                          newbie->ipsacq_numpackets = ipsacq_maxpackets;
5645 5655                          lastone = newbie->ipsacq_mp;
5646 5656                          newbie->ipsacq_mp = lastone->b_next;
5647 5657                          lastone->b_next = NULL;
5648 5658  
5649 5659                          /* Freeing the async message */
5650 5660                          lastone = ip_xmit_attr_free_mblk(lastone);
5651 5661                          ip_drop_packet(lastone, B_FALSE, NULL,
5652 5662                              DROPPER(ipss, ipds_sadb_acquire_toofull),
5653 5663                              &ipss->ipsec_sadb_dropper);
5654 5664                  } else {
5655 5665                          IP_ACQUIRE_STAT(ipss, qhiwater,
5656 5666                              newbie->ipsacq_numpackets);
5657 5667                  }
5658 5668          }
5659 5669  
5660 5670          /*
5661 5671           * Reset addresses.  Set them to the most recently added mblk chain,
5662 5672           * so that the address pointers in the acquire record will point
5663 5673           * at an mblk still attached to the acquire list.
5664 5674           */
5665 5675  
5666 5676          newbie->ipsacq_srcaddr = src;
5667 5677          newbie->ipsacq_dstaddr = dst;
5668 5678  
5669 5679          /*
5670 5680           * If the acquire record has more than one queued packet, we've
5671 5681           * already sent an ACQUIRE, and don't need to repeat ourself.
5672 5682           */
5673 5683          if (newbie->ipsacq_seq != seq || newbie->ipsacq_numpackets > 1) {
5674 5684                  /* I have an acquire outstanding already! */
5675 5685                  mutex_exit(&newbie->ipsacq_lock);
5676 5686                  return;
5677 5687          }
5678 5688  
5679 5689          if (need_esp) {
5680 5690                  ESP_BUMP_STAT(espstack, acquire_requests);
5681 5691                  q = espstack->esp_pfkey_q;
5682 5692          } else {
5683 5693                  /*
5684 5694                   * Two cases get us here:
5685 5695                   * 1.) AH-only policy.
5686 5696                   *
5687 5697                   * 2.) A continuation of an AH+ESP policy, and this is the
5688 5698                   * post-ESP, AH-needs-to-send-a-regular-ACQUIRE case.
5689 5699                   * (i.e. called from esp_do_outbound_ah().)
5690 5700                   */
5691 5701                  AH_BUMP_STAT(ahstack, acquire_requests);
5692 5702                  q = ahstack->ah_pfkey_q;
5693 5703          }
5694 5704  
5695 5705          /*
5696 5706           * Get selectors and other policy-expression bits needed for an
5697 5707           * ACQUIRE.
5698 5708           */
5699 5709          bzero(&sel, sizeof (sel));
5700 5710          sel.ips_isv4 = (ixa->ixa_flags & IXAF_IS_IPV4) != 0;
5701 5711          if (tunnel_mode) {
5702 5712                  sel.ips_protocol = (ixa->ixa_ipsec_inaf == AF_INET) ?
5703 5713                      IPPROTO_ENCAP : IPPROTO_IPV6;
5704 5714          } else {
5705 5715                  sel.ips_protocol = ixa->ixa_ipsec_proto;
5706 5716                  sel.ips_local_port = ixa->ixa_ipsec_src_port;
5707 5717                  sel.ips_remote_port = ixa->ixa_ipsec_dst_port;
5708 5718          }
5709 5719          sel.ips_icmp_type = ixa->ixa_ipsec_icmp_type;
5710 5720          sel.ips_icmp_code = ixa->ixa_ipsec_icmp_code;
5711 5721          sel.ips_is_icmp_inv_acq = 0;
5712 5722          if (af == AF_INET) {
5713 5723                  sel.ips_local_addr_v4 = ipha->ipha_src;
5714 5724                  sel.ips_remote_addr_v4 = ipha->ipha_dst;
5715 5725          } else {
5716 5726                  sel.ips_local_addr_v6 = ip6h->ip6_src;
5717 5727                  sel.ips_remote_addr_v6 = ip6h->ip6_dst;
5718 5728          }
5719 5729  
5720 5730  
5721 5731          /*
5722 5732           * 1. Generate addresses, kmc, and sensitivity.  These are "common"
5723 5733           * and should be an mblk pointed to by common. TBD -- eventually it
5724 5734           * will include triggering packet contents as more address extensions.
5725 5735           *
5726 5736           * 2. Generate ACQUIRE & KEYSOCK_OUT and single-protocol proposal.
5727 5737           * These are "regular" and "prop".  String regular->b_cont->b_cont =
5728 5738           * common, common->b_cont = prop.
5729 5739           *
5730 5740           * 3. If extended register got turned on, generate EXT_ACQUIRE &
5731 5741           * KEYSOCK_OUT and multi-protocol eprop. These are "extended" and
5732 5742           * "eprop".  String extended->b_cont->b_cont = dupb(common) and
5733 5743           * extended->b_cont->b_cont->b_cont = prop.
5734 5744           *
5735 5745           * 4. Deliver:  putnext(q, regular) and if there, putnext(q, extended).
5736 5746           */
5737 5747  
5738 5748          regular = extended = prop = eprop = NULL;
5739 5749  
5740 5750          common = sadb_acquire_msg_common(&sel, pp, ap, tunnel_mode, tsl, NULL);
5741 5751          if (common == NULL)
5742 5752                  goto bail;
5743 5753  
5744 5754          regular = sadb_acquire_msg_base(0, (need_esp ?
5745 5755              SADB_SATYPE_ESP : SADB_SATYPE_AH), newbie->ipsacq_seq, 0);
5746 5756          if (regular == NULL)
5747 5757                  goto bail;
5748 5758  
5749 5759          /*
5750 5760           * Pardon the boolean cleverness. At least one of need_* must be true.
5751 5761           * If they are equal, it's an AH & ESP policy and ESP needs to go
5752 5762           * first.  If they aren't, just check the contents of need_esp.
5753 5763           */
5754 5764          prop = sadb_acquire_prop(ap, ns, need_esp);
5755 5765          if (prop == NULL)
5756 5766                  goto bail;
5757 5767  
5758 5768          /* Link the parts together. */
5759 5769          regular->b_cont->b_cont = common;
5760 5770          common->b_cont = prop;
5761 5771          /*
5762 5772           * Prop is now linked, so don't freemsg() it if the extended
5763 5773           * construction goes off the rails.
5764 5774           */
5765 5775          prop = NULL;
5766 5776  
5767 5777          ((sadb_msg_t *)(regular->b_cont->b_rptr))->sadb_msg_len =
5768 5778              SADB_8TO64(msgsize(regular->b_cont));
5769 5779  
5770 5780          /*
5771 5781           * If we need an extended ACQUIRE, build it here.
5772 5782           */
5773 5783          if (keysock_extended_reg(ns)) {
5774 5784                  /* NOTE: "common" still points to what we need. */
5775 5785                  extended = sadb_acquire_msg_base(0, 0, newbie->ipsacq_seq, 0);
5776 5786                  if (extended == NULL) {
5777 5787                          common = NULL;
5778 5788                          goto bail;
5779 5789                  }
5780 5790  
5781 5791                  extended->b_cont->b_cont = dupb(common);
5782 5792                  common = NULL;
5783 5793                  if (extended->b_cont->b_cont == NULL)
5784 5794                          goto bail;
5785 5795  
5786 5796                  eprop = sadb_acquire_extended_prop(ap, ns);
5787 5797                  if (eprop == NULL)
5788 5798                          goto bail;
5789 5799                  extended->b_cont->b_cont->b_cont = eprop;
5790 5800  
5791 5801                  ((sadb_msg_t *)(extended->b_cont->b_rptr))->sadb_msg_len =
5792 5802                      SADB_8TO64(msgsize(extended->b_cont));
5793 5803          }
5794 5804  
5795 5805          /* So we don't hold a lock across putnext()... */
5796 5806          mutex_exit(&newbie->ipsacq_lock);
5797 5807  
5798 5808          if (extended != NULL)
5799 5809                  putnext(q, extended);
5800 5810          ASSERT(regular != NULL);
5801 5811          putnext(q, regular);
5802 5812          return;
5803 5813  
5804 5814  bail:
5805 5815          /* Make this acquire record go away quickly... */
5806 5816          newbie->ipsacq_expire = 0;
5807 5817          /* Exploit freemsg(NULL) being legal for fun & profit. */
5808 5818          freemsg(common);
5809 5819          freemsg(prop);
5810 5820          freemsg(extended);
5811 5821          freemsg(regular);
5812 5822          mutex_exit(&newbie->ipsacq_lock);
5813 5823  }
5814 5824  
5815 5825  /*
5816 5826   * Unlink and free an acquire record.
5817 5827   */
5818 5828  void
5819 5829  sadb_destroy_acquire(ipsacq_t *acqrec, netstack_t *ns)
5820 5830  {
5821 5831          mblk_t          *mp;
5822 5832          ipsec_stack_t   *ipss = ns->netstack_ipsec;
5823 5833  
5824 5834          ASSERT(MUTEX_HELD(acqrec->ipsacq_linklock));
5825 5835  
5826 5836          if (acqrec->ipsacq_policy != NULL) {
5827 5837                  IPPOL_REFRELE(acqrec->ipsacq_policy);
5828 5838          }
5829 5839          if (acqrec->ipsacq_act != NULL) {
5830 5840                  IPACT_REFRELE(acqrec->ipsacq_act);
5831 5841          }
5832 5842  
5833 5843          /* Unlink */
5834 5844          *(acqrec->ipsacq_ptpn) = acqrec->ipsacq_next;
5835 5845          if (acqrec->ipsacq_next != NULL)
5836 5846                  acqrec->ipsacq_next->ipsacq_ptpn = acqrec->ipsacq_ptpn;
5837 5847  
5838 5848          if (acqrec->ipsacq_tsl != NULL) {
5839 5849                  label_rele(acqrec->ipsacq_tsl);
5840 5850                  acqrec->ipsacq_tsl = NULL;
5841 5851          }
5842 5852  
5843 5853          /*
5844 5854           * Free hanging mp's.
5845 5855           *
5846 5856           * XXX Instead of freemsg(), perhaps use IPSEC_REQ_FAILED.
5847 5857           */
5848 5858  
5849 5859          mutex_enter(&acqrec->ipsacq_lock);
5850 5860          while (acqrec->ipsacq_mp != NULL) {
5851 5861                  mp = acqrec->ipsacq_mp;
5852 5862                  acqrec->ipsacq_mp = mp->b_next;
5853 5863                  mp->b_next = NULL;
5854 5864                  /* Freeing the async message */
5855 5865                  mp = ip_xmit_attr_free_mblk(mp);
5856 5866                  ip_drop_packet(mp, B_FALSE, NULL,
5857 5867                      DROPPER(ipss, ipds_sadb_acquire_timeout),
5858 5868                      &ipss->ipsec_sadb_dropper);
5859 5869          }
5860 5870          mutex_exit(&acqrec->ipsacq_lock);
5861 5871  
5862 5872          /* Free */
5863 5873          mutex_destroy(&acqrec->ipsacq_lock);
5864 5874          kmem_free(acqrec, sizeof (*acqrec));
5865 5875  }
5866 5876  
5867 5877  /*
5868 5878   * Destroy an acquire list fanout.
5869 5879   */
5870 5880  static void
5871 5881  sadb_destroy_acqlist(iacqf_t **listp, uint_t numentries, boolean_t forever,
5872 5882      netstack_t *ns)
5873 5883  {
5874 5884          int i;
5875 5885          iacqf_t *list = *listp;
5876 5886  
5877 5887          if (list == NULL)
5878 5888                  return;
5879 5889  
5880 5890          for (i = 0; i < numentries; i++) {
5881 5891                  mutex_enter(&(list[i].iacqf_lock));
5882 5892                  while (list[i].iacqf_ipsacq != NULL)
5883 5893                          sadb_destroy_acquire(list[i].iacqf_ipsacq, ns);
5884 5894                  mutex_exit(&(list[i].iacqf_lock));
5885 5895                  if (forever)
5886 5896                          mutex_destroy(&(list[i].iacqf_lock));
5887 5897          }
5888 5898  
5889 5899          if (forever) {
5890 5900                  *listp = NULL;
5891 5901                  kmem_free(list, numentries * sizeof (*list));
5892 5902          }
5893 5903  }
5894 5904  
5895 5905  /*
5896 5906   * Create an algorithm descriptor for an extended ACQUIRE.  Filter crypto
5897 5907   * framework's view of reality vs. IPsec's.  EF's wins, BTW.
5898 5908   */
5899 5909  static uint8_t *
5900 5910  sadb_new_algdesc(uint8_t *start, uint8_t *limit,
5901 5911      sadb_x_ecomb_t *ecomb, uint8_t satype, uint8_t algtype,
5902 5912      uint8_t alg, uint16_t minbits, uint16_t maxbits, ipsec_stack_t *ipss)
5903 5913  {
5904 5914          uint8_t *cur = start;
5905 5915          ipsec_alginfo_t *algp;
5906 5916          sadb_x_algdesc_t *algdesc = (sadb_x_algdesc_t *)cur;
5907 5917  
5908 5918          cur += sizeof (*algdesc);
5909 5919          if (cur >= limit)
5910 5920                  return (NULL);
5911 5921  
5912 5922          ecomb->sadb_x_ecomb_numalgs++;
5913 5923  
5914 5924          /*
5915 5925           * Normalize vs. crypto framework's limits.  This way, you can specify
5916 5926           * a stronger policy, and when the framework loads a stronger version,
5917 5927           * you can just keep plowing w/o rewhacking your SPD.
5918 5928           */
5919 5929          rw_enter(&ipss->ipsec_alg_lock, RW_READER);
5920 5930          algp = ipss->ipsec_alglists[(algtype == SADB_X_ALGTYPE_AUTH) ?
5921 5931              IPSEC_ALG_AUTH : IPSEC_ALG_ENCR][alg];
5922 5932          if (algp == NULL) {
5923 5933                  rw_exit(&ipss->ipsec_alg_lock);
5924 5934                  return (NULL);  /* Algorithm doesn't exist.  Fail gracefully. */
5925 5935          }
5926 5936          if (minbits < algp->alg_ef_minbits)
5927 5937                  minbits = algp->alg_ef_minbits;
5928 5938          if (maxbits > algp->alg_ef_maxbits)
5929 5939                  maxbits = algp->alg_ef_maxbits;
5930 5940          rw_exit(&ipss->ipsec_alg_lock);
5931 5941  
5932 5942          algdesc->sadb_x_algdesc_reserved = SADB_8TO1(algp->alg_saltlen);
5933 5943          algdesc->sadb_x_algdesc_satype = satype;
5934 5944          algdesc->sadb_x_algdesc_algtype = algtype;
5935 5945          algdesc->sadb_x_algdesc_alg = alg;
5936 5946          algdesc->sadb_x_algdesc_minbits = minbits;
5937 5947          algdesc->sadb_x_algdesc_maxbits = maxbits;
5938 5948  
5939 5949          return (cur);
5940 5950  }
5941 5951  
5942 5952  /*
5943 5953   * Convert the given ipsec_action_t into an ecomb starting at *ecomb
5944 5954   * which must fit before *limit
5945 5955   *
5946 5956   * return NULL if we ran out of room or a pointer to the end of the ecomb.
5947 5957   */
5948 5958  static uint8_t *
5949 5959  sadb_action_to_ecomb(uint8_t *start, uint8_t *limit, ipsec_action_t *act,
5950 5960      netstack_t *ns)
5951 5961  {
5952 5962          uint8_t *cur = start;
5953 5963          sadb_x_ecomb_t *ecomb = (sadb_x_ecomb_t *)cur;
5954 5964          ipsec_prot_t *ipp;
5955 5965          ipsec_stack_t *ipss = ns->netstack_ipsec;
5956 5966  
5957 5967          cur += sizeof (*ecomb);
5958 5968          if (cur >= limit)
5959 5969                  return (NULL);
5960 5970  
5961 5971          ASSERT(act->ipa_act.ipa_type == IPSEC_ACT_APPLY);
5962 5972  
5963 5973          ipp = &act->ipa_act.ipa_apply;
5964 5974  
5965 5975          ecomb->sadb_x_ecomb_numalgs = 0;
5966 5976          ecomb->sadb_x_ecomb_reserved = 0;
5967 5977          ecomb->sadb_x_ecomb_reserved2 = 0;
5968 5978          /*
5969 5979           * No limits on allocations, since we really don't support that
5970 5980           * concept currently.
5971 5981           */
5972 5982          ecomb->sadb_x_ecomb_soft_allocations = 0;
5973 5983          ecomb->sadb_x_ecomb_hard_allocations = 0;
5974 5984  
5975 5985          /*
5976 5986           * XXX TBD: Policy or global parameters will eventually be
5977 5987           * able to fill in some of these.
5978 5988           */
5979 5989          ecomb->sadb_x_ecomb_flags = 0;
5980 5990          ecomb->sadb_x_ecomb_soft_bytes = 0;
5981 5991          ecomb->sadb_x_ecomb_hard_bytes = 0;
5982 5992          ecomb->sadb_x_ecomb_soft_addtime = 0;
5983 5993          ecomb->sadb_x_ecomb_hard_addtime = 0;
5984 5994          ecomb->sadb_x_ecomb_soft_usetime = 0;
5985 5995          ecomb->sadb_x_ecomb_hard_usetime = 0;
5986 5996  
5987 5997          if (ipp->ipp_use_ah) {
5988 5998                  cur = sadb_new_algdesc(cur, limit, ecomb,
5989 5999                      SADB_SATYPE_AH, SADB_X_ALGTYPE_AUTH, ipp->ipp_auth_alg,
5990 6000                      ipp->ipp_ah_minbits, ipp->ipp_ah_maxbits, ipss);
5991 6001                  if (cur == NULL)
5992 6002                          return (NULL);
5993 6003                  ipsecah_fill_defs(ecomb, ns);
5994 6004          }
5995 6005  
5996 6006          if (ipp->ipp_use_esp) {
5997 6007                  if (ipp->ipp_use_espa) {
5998 6008                          cur = sadb_new_algdesc(cur, limit, ecomb,
5999 6009                              SADB_SATYPE_ESP, SADB_X_ALGTYPE_AUTH,
6000 6010                              ipp->ipp_esp_auth_alg,
6001 6011                              ipp->ipp_espa_minbits,
6002 6012                              ipp->ipp_espa_maxbits, ipss);
6003 6013                          if (cur == NULL)
6004 6014                                  return (NULL);
6005 6015                  }
6006 6016  
6007 6017                  cur = sadb_new_algdesc(cur, limit, ecomb,
6008 6018                      SADB_SATYPE_ESP, SADB_X_ALGTYPE_CRYPT,
6009 6019                      ipp->ipp_encr_alg,
6010 6020                      ipp->ipp_espe_minbits,
6011 6021                      ipp->ipp_espe_maxbits, ipss);
6012 6022                  if (cur == NULL)
6013 6023                          return (NULL);
6014 6024                  /* Fill in lifetimes if and only if AH didn't already... */
6015 6025                  if (!ipp->ipp_use_ah)
6016 6026                          ipsecesp_fill_defs(ecomb, ns);
6017 6027          }
6018 6028  
6019 6029          return (cur);
6020 6030  }
6021 6031  
6022 6032  #include <sys/tsol/label_macro.h> /* XXX should not need this */
6023 6033  
6024 6034  /*
6025 6035   * From a cred_t, construct a sensitivity label extension
6026 6036   *
6027 6037   * We send up a fixed-size sensitivity label bitmap, and are perhaps
6028 6038   * overly chummy with the underlying data structures here.
6029 6039   */
6030 6040  
6031 6041  /* ARGSUSED */
6032 6042  int
6033 6043  sadb_sens_len_from_label(ts_label_t *tsl)
6034 6044  {
6035 6045          int baselen = sizeof (sadb_sens_t) + _C_LEN * 4;
6036 6046          return (roundup(baselen, sizeof (uint64_t)));
6037 6047  }
6038 6048  
6039 6049  void
6040 6050  sadb_sens_from_label(sadb_sens_t *sens, int exttype, ts_label_t *tsl,
6041 6051      int senslen)
6042 6052  {
6043 6053          uint8_t *bitmap;
6044 6054          bslabel_t *sl;
6045 6055  
6046 6056          /* LINTED */
6047 6057          ASSERT((_C_LEN & 1) == 0);
6048 6058          ASSERT((senslen & 7) == 0);
6049 6059  
6050 6060          sl = label2bslabel(tsl);
6051 6061  
6052 6062          sens->sadb_sens_exttype = exttype;
6053 6063          sens->sadb_sens_len = SADB_8TO64(senslen);
6054 6064  
6055 6065          sens->sadb_sens_dpd = tsl->tsl_doi;
6056 6066          sens->sadb_sens_sens_level = LCLASS(sl);
6057 6067          sens->sadb_sens_integ_level = 0; /* TBD */
6058 6068          sens->sadb_sens_sens_len = _C_LEN >> 1;
6059 6069          sens->sadb_sens_integ_len = 0; /* TBD */
6060 6070          sens->sadb_x_sens_flags = 0;
6061 6071  
6062 6072          bitmap = (uint8_t *)(sens + 1);
6063 6073          bcopy(&(((_bslabel_impl_t *)sl)->compartments), bitmap, _C_LEN * 4);
6064 6074  }
6065 6075  
6066 6076  /*
6067 6077   * Okay, how do we report errors/invalid labels from this?
6068 6078   * With a special designated "not a label" cred_t ?
6069 6079   */
6070 6080  /* ARGSUSED */
6071 6081  ts_label_t *
6072 6082  sadb_label_from_sens(sadb_sens_t *sens, uint64_t *bitmap)
6073 6083  {
6074 6084          int bitmap_len = SADB_64TO8(sens->sadb_sens_sens_len);
6075 6085          bslabel_t sl;
6076 6086          ts_label_t *tsl;
6077 6087  
6078 6088          if (sens->sadb_sens_integ_level != 0)
6079 6089                  return (NULL);
6080 6090          if (sens->sadb_sens_integ_len != 0)
6081 6091                  return (NULL);
6082 6092          if (bitmap_len > _C_LEN * 4)
6083 6093                  return (NULL);
6084 6094  
6085 6095          bsllow(&sl);
6086 6096          LCLASS_SET((_bslabel_impl_t *)&sl, sens->sadb_sens_sens_level);
6087 6097          bcopy(bitmap, &((_bslabel_impl_t *)&sl)->compartments,
6088 6098              bitmap_len);
6089 6099  
6090 6100          tsl = labelalloc(&sl, sens->sadb_sens_dpd, KM_NOSLEEP);
6091 6101          if (tsl == NULL)
6092 6102                  return (NULL);
6093 6103  
6094 6104          if (sens->sadb_x_sens_flags & SADB_X_SENS_UNLABELED)
6095 6105                  tsl->tsl_flags |= TSLF_UNLABELED;
6096 6106          return (tsl);
6097 6107  }
6098 6108  
6099 6109  /* End XXX label-library-leakage */
6100 6110  
6101 6111  /*
6102 6112   * Given an SADB_GETSPI message, find an appropriately ranged SA and
6103 6113   * allocate an SA.  If there are message improprieties, return (ipsa_t *)-1.
6104 6114   * If there was a memory allocation error, return NULL.  (Assume NULL !=
6105 6115   * (ipsa_t *)-1).
6106 6116   *
6107 6117   * master_spi is passed in host order.
6108 6118   */
6109 6119  ipsa_t *
6110 6120  sadb_getspi(keysock_in_t *ksi, uint32_t master_spi, int *diagnostic,
6111 6121      netstack_t *ns, uint_t sa_type)
6112 6122  {
6113 6123          sadb_address_t *src =
6114 6124              (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_SRC],
6115 6125              *dst = (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_DST];
6116 6126          sadb_spirange_t *range =
6117 6127              (sadb_spirange_t *)ksi->ks_in_extv[SADB_EXT_SPIRANGE];
6118 6128          struct sockaddr_in *ssa, *dsa;
6119 6129          struct sockaddr_in6 *ssa6, *dsa6;
6120 6130          uint32_t *srcaddr, *dstaddr;
6121 6131          sa_family_t af;
6122 6132          uint32_t add, min, max;
6123 6133          uint8_t protocol =
6124 6134              (sa_type == SADB_SATYPE_AH) ? IPPROTO_AH : IPPROTO_ESP;
6125 6135  
6126 6136          if (src == NULL) {
6127 6137                  *diagnostic = SADB_X_DIAGNOSTIC_MISSING_SRC;
6128 6138                  return ((ipsa_t *)-1);
6129 6139          }
6130 6140          if (dst == NULL) {
6131 6141                  *diagnostic = SADB_X_DIAGNOSTIC_MISSING_DST;
6132 6142                  return ((ipsa_t *)-1);
6133 6143          }
6134 6144          if (range == NULL) {
6135 6145                  *diagnostic = SADB_X_DIAGNOSTIC_MISSING_RANGE;
6136 6146                  return ((ipsa_t *)-1);
6137 6147          }
6138 6148  
6139 6149          min = ntohl(range->sadb_spirange_min);
6140 6150          max = ntohl(range->sadb_spirange_max);
6141 6151          dsa = (struct sockaddr_in *)(dst + 1);
6142 6152          dsa6 = (struct sockaddr_in6 *)dsa;
6143 6153  
6144 6154          ssa = (struct sockaddr_in *)(src + 1);
6145 6155          ssa6 = (struct sockaddr_in6 *)ssa;
6146 6156          ASSERT(dsa->sin_family == ssa->sin_family);
6147 6157  
6148 6158          srcaddr = ALL_ZEROES_PTR;
6149 6159          af = dsa->sin_family;
6150 6160          switch (af) {
6151 6161          case AF_INET:
6152 6162                  if (src != NULL)
6153 6163                          srcaddr = (uint32_t *)(&ssa->sin_addr);
6154 6164                  dstaddr = (uint32_t *)(&dsa->sin_addr);
6155 6165                  break;
6156 6166          case AF_INET6:
6157 6167                  if (src != NULL)
6158 6168                          srcaddr = (uint32_t *)(&ssa6->sin6_addr);
6159 6169                  dstaddr = (uint32_t *)(&dsa6->sin6_addr);
6160 6170                  break;
6161 6171          default:
6162 6172                  *diagnostic = SADB_X_DIAGNOSTIC_BAD_DST_AF;
6163 6173                  return ((ipsa_t *)-1);
6164 6174          }
6165 6175  
6166 6176          if (master_spi < min || master_spi > max) {
6167 6177                  /* Return a random value in the range. */
6168 6178                  if (cl_inet_getspi) {
6169 6179                          cl_inet_getspi(ns->netstack_stackid, protocol,
6170 6180                              (uint8_t *)&add, sizeof (add), NULL);
6171 6181                  } else {
6172 6182                          (void) random_get_pseudo_bytes((uint8_t *)&add,
6173 6183                              sizeof (add));
6174 6184                  }
6175 6185                  master_spi = min + (add % (max - min + 1));
6176 6186          }
6177 6187  
6178 6188          /*
6179 6189           * Since master_spi is passed in host order, we need to htonl() it
6180 6190           * for the purposes of creating a new SA.
6181 6191           */
6182 6192          return (sadb_makelarvalassoc(htonl(master_spi), srcaddr, dstaddr, af,
6183 6193              ns));
6184 6194  }
6185 6195  
6186 6196  /*
6187 6197   *
6188 6198   * Locate an ACQUIRE and nuke it.  If I have an samsg that's larger than the
6189 6199   * base header, just ignore it.  Otherwise, lock down the whole ACQUIRE list
6190 6200   * and scan for the sequence number in question.  I may wish to accept an
6191 6201   * address pair with it, for easier searching.
6192 6202   *
6193 6203   * Caller frees the message, so we don't have to here.
6194 6204   *
6195 6205   * NOTE:        The pfkey_q parameter may be used in the future for ACQUIRE
6196 6206   *              failures.
6197 6207   */
6198 6208  /* ARGSUSED */
6199 6209  void
6200 6210  sadb_in_acquire(sadb_msg_t *samsg, sadbp_t *sp, queue_t *pfkey_q,
6201 6211      netstack_t *ns)
6202 6212  {
6203 6213          int i;
6204 6214          ipsacq_t *acqrec;
6205 6215          iacqf_t *bucket;
6206 6216  
6207 6217          /*
6208 6218           * I only accept the base header for this!
6209 6219           * Though to be honest, requiring the dst address would help
6210 6220           * immensely.
6211 6221           *
6212 6222           * XXX  There are already cases where I can get the dst address.
6213 6223           */
6214 6224          if (samsg->sadb_msg_len > SADB_8TO64(sizeof (*samsg)))
6215 6225                  return;
6216 6226  
6217 6227          /*
6218 6228           * Using the samsg->sadb_msg_seq, find the ACQUIRE record, delete it,
6219 6229           * (and in the future send a message to IP with the appropriate error
6220 6230           * number).
6221 6231           *
6222 6232           * Q: Do I want to reject if pid != 0?
6223 6233           */
6224 6234  
6225 6235          for (i = 0; i < sp->s_v4.sdb_hashsize; i++) {
6226 6236                  bucket = &sp->s_v4.sdb_acq[i];
6227 6237                  mutex_enter(&bucket->iacqf_lock);
6228 6238                  for (acqrec = bucket->iacqf_ipsacq; acqrec != NULL;
6229 6239                      acqrec = acqrec->ipsacq_next) {
6230 6240                          if (samsg->sadb_msg_seq == acqrec->ipsacq_seq)
6231 6241                                  break;  /* for acqrec... loop. */
6232 6242                  }
6233 6243                  if (acqrec != NULL)
6234 6244                          break;  /* for i = 0... loop. */
6235 6245  
6236 6246                  mutex_exit(&bucket->iacqf_lock);
6237 6247          }
6238 6248  
6239 6249          if (acqrec == NULL) {
6240 6250                  for (i = 0; i < sp->s_v6.sdb_hashsize; i++) {
6241 6251                          bucket = &sp->s_v6.sdb_acq[i];
6242 6252                          mutex_enter(&bucket->iacqf_lock);
6243 6253                          for (acqrec = bucket->iacqf_ipsacq; acqrec != NULL;
6244 6254                              acqrec = acqrec->ipsacq_next) {
6245 6255                                  if (samsg->sadb_msg_seq == acqrec->ipsacq_seq)
6246 6256                                          break;  /* for acqrec... loop. */
6247 6257                          }
6248 6258                          if (acqrec != NULL)
6249 6259                                  break;  /* for i = 0... loop. */
6250 6260  
6251 6261                          mutex_exit(&bucket->iacqf_lock);
6252 6262                  }
6253 6263          }
6254 6264  
6255 6265  
6256 6266          if (acqrec == NULL)
6257 6267                  return;
6258 6268  
6259 6269          /*
6260 6270           * What do I do with the errno and IP?  I may need mp's services a
6261 6271           * little more.  See sadb_destroy_acquire() for future directions
6262 6272           * beyond free the mblk chain on the acquire record.
6263 6273           */
6264 6274  
6265 6275          ASSERT(&bucket->iacqf_lock == acqrec->ipsacq_linklock);
6266 6276          sadb_destroy_acquire(acqrec, ns);
6267 6277          /* Have to exit mutex here, because of breaking out of for loop. */
6268 6278          mutex_exit(&bucket->iacqf_lock);
6269 6279  }
6270 6280  
6271 6281  /*
6272 6282   * The following functions work with the replay windows of an SA.  They assume
6273 6283   * the ipsa->ipsa_replay_arr is an array of uint64_t, and that the bit vector
6274 6284   * represents the highest sequence number packet received, and back
6275 6285   * (ipsa->ipsa_replay_wsize) packets.
6276 6286   */
6277 6287  
6278 6288  /*
6279 6289   * Is the replay bit set?
6280 6290   */
6281 6291  static boolean_t
6282 6292  ipsa_is_replay_set(ipsa_t *ipsa, uint32_t offset)
6283 6293  {
6284 6294          uint64_t bit = (uint64_t)1 << (uint64_t)(offset & 63);
6285 6295  
6286 6296          return ((bit & ipsa->ipsa_replay_arr[offset >> 6]) ? B_TRUE : B_FALSE);
6287 6297  }
6288 6298  
6289 6299  /*
6290 6300   * Shift the bits of the replay window over.
6291 6301   */
6292 6302  static void
6293 6303  ipsa_shift_replay(ipsa_t *ipsa, uint32_t shift)
6294 6304  {
6295 6305          int i;
6296 6306          int jump = ((shift - 1) >> 6) + 1;
6297 6307  
6298 6308          if (shift == 0)
6299 6309                  return;
6300 6310  
6301 6311          for (i = (ipsa->ipsa_replay_wsize - 1) >> 6; i >= 0; i--) {
6302 6312                  if (i + jump <= (ipsa->ipsa_replay_wsize - 1) >> 6) {
6303 6313                          ipsa->ipsa_replay_arr[i + jump] |=
6304 6314                              ipsa->ipsa_replay_arr[i] >> (64 - (shift & 63));
6305 6315                  }
6306 6316                  ipsa->ipsa_replay_arr[i] <<= shift;
6307 6317          }
6308 6318  }
6309 6319  
6310 6320  /*
6311 6321   * Set a bit in the bit vector.
6312 6322   */
6313 6323  static void
6314 6324  ipsa_set_replay(ipsa_t *ipsa, uint32_t offset)
6315 6325  {
6316 6326          uint64_t bit = (uint64_t)1 << (uint64_t)(offset & 63);
6317 6327  
6318 6328          ipsa->ipsa_replay_arr[offset >> 6] |= bit;
6319 6329  }
6320 6330  
6321 6331  #define SADB_MAX_REPLAY_VALUE 0xffffffff
6322 6332  
6323 6333  /*
6324 6334   * Assume caller has NOT done ntohl() already on seq.  Check to see
6325 6335   * if replay sequence number "seq" has been seen already.
6326 6336   */
6327 6337  boolean_t
6328 6338  sadb_replay_check(ipsa_t *ipsa, uint32_t seq)
6329 6339  {
6330 6340          boolean_t rc;
6331 6341          uint32_t diff;
6332 6342  
6333 6343          if (ipsa->ipsa_replay_wsize == 0)
6334 6344                  return (B_TRUE);
6335 6345  
6336 6346          /*
6337 6347           * NOTE:  I've already checked for 0 on the wire in sadb_replay_peek().
6338 6348           */
6339 6349  
6340 6350          /* Convert sequence number into host order before holding the mutex. */
6341 6351          seq = ntohl(seq);
6342 6352  
6343 6353          mutex_enter(&ipsa->ipsa_lock);
6344 6354  
6345 6355          /* Initialize inbound SA's ipsa_replay field to last one received. */
6346 6356          if (ipsa->ipsa_replay == 0)
6347 6357                  ipsa->ipsa_replay = 1;
6348 6358  
6349 6359          if (seq > ipsa->ipsa_replay) {
6350 6360                  /*
6351 6361                   * I have received a new "highest value received".  Shift
6352 6362                   * the replay window over.
6353 6363                   */
6354 6364                  diff = seq - ipsa->ipsa_replay;
6355 6365                  if (diff < ipsa->ipsa_replay_wsize) {
6356 6366                          /* In replay window, shift bits over. */
6357 6367                          ipsa_shift_replay(ipsa, diff);
6358 6368                  } else {
6359 6369                          /* WAY FAR AHEAD, clear bits and start again. */
6360 6370                          bzero(ipsa->ipsa_replay_arr,
6361 6371                              sizeof (ipsa->ipsa_replay_arr));
6362 6372                  }
6363 6373                  ipsa_set_replay(ipsa, 0);
6364 6374                  ipsa->ipsa_replay = seq;
6365 6375                  rc = B_TRUE;
6366 6376                  goto done;
6367 6377          }
6368 6378          diff = ipsa->ipsa_replay - seq;
6369 6379          if (diff >= ipsa->ipsa_replay_wsize || ipsa_is_replay_set(ipsa, diff)) {
6370 6380                  rc = B_FALSE;
6371 6381                  goto done;
6372 6382          }
6373 6383          /* Set this packet as seen. */
6374 6384          ipsa_set_replay(ipsa, diff);
6375 6385  
6376 6386          rc = B_TRUE;
6377 6387  done:
6378 6388          mutex_exit(&ipsa->ipsa_lock);
6379 6389          return (rc);
6380 6390  }
6381 6391  
6382 6392  /*
6383 6393   * "Peek" and see if we should even bother going through the effort of
6384 6394   * running an authentication check on the sequence number passed in.
6385 6395   * this takes into account packets that are below the replay window,
6386 6396   * and collisions with already replayed packets.  Return B_TRUE if it
6387 6397   * is okay to proceed, B_FALSE if this packet should be dropped immediately.
6388 6398   * Assume same byte-ordering as sadb_replay_check.
6389 6399   */
6390 6400  boolean_t
6391 6401  sadb_replay_peek(ipsa_t *ipsa, uint32_t seq)
6392 6402  {
6393 6403          boolean_t rc = B_FALSE;
6394 6404          uint32_t diff;
6395 6405  
6396 6406          if (ipsa->ipsa_replay_wsize == 0)
6397 6407                  return (B_TRUE);
6398 6408  
6399 6409          /*
6400 6410           * 0 is 0, regardless of byte order... :)
6401 6411           *
6402 6412           * If I get 0 on the wire (and there is a replay window) then the
6403 6413           * sender most likely wrapped.  This ipsa may need to be marked or
6404 6414           * something.
6405 6415           */
6406 6416          if (seq == 0)
6407 6417                  return (B_FALSE);
6408 6418  
6409 6419          seq = ntohl(seq);
6410 6420          mutex_enter(&ipsa->ipsa_lock);
6411 6421          if (seq < ipsa->ipsa_replay - ipsa->ipsa_replay_wsize &&
6412 6422              ipsa->ipsa_replay >= ipsa->ipsa_replay_wsize)
6413 6423                  goto done;
6414 6424  
6415 6425          /*
6416 6426           * If I've hit 0xffffffff, then quite honestly, I don't need to
6417 6427           * bother with formalities.  I'm not accepting any more packets
6418 6428           * on this SA.
6419 6429           */
6420 6430          if (ipsa->ipsa_replay == SADB_MAX_REPLAY_VALUE) {
6421 6431                  /*
6422 6432                   * Since we're already holding the lock, update the
6423 6433                   * expire time ala. sadb_replay_delete() and return.
6424 6434                   */
6425 6435                  ipsa->ipsa_hardexpiretime = (time_t)1;
6426 6436                  goto done;
6427 6437          }
6428 6438  
6429 6439          if (seq <= ipsa->ipsa_replay) {
6430 6440                  /*
6431 6441                   * This seq is in the replay window.  I'm not below it,
6432 6442                   * because I already checked for that above!
6433 6443                   */
6434 6444                  diff = ipsa->ipsa_replay - seq;
6435 6445                  if (ipsa_is_replay_set(ipsa, diff))
6436 6446                          goto done;
6437 6447          }
6438 6448          /* Else return B_TRUE, I'm going to advance the window. */
6439 6449  
6440 6450          rc = B_TRUE;
6441 6451  done:
6442 6452          mutex_exit(&ipsa->ipsa_lock);
6443 6453          return (rc);
6444 6454  }
6445 6455  
6446 6456  /*
6447 6457   * Delete a single SA.
6448 6458   *
6449 6459   * For now, use the quick-and-dirty trick of making the association's
6450 6460   * hard-expire lifetime (time_t)1, ensuring deletion by the *_ager().
6451 6461   */
6452 6462  void
6453 6463  sadb_replay_delete(ipsa_t *assoc)
6454 6464  {
6455 6465          mutex_enter(&assoc->ipsa_lock);
6456 6466          assoc->ipsa_hardexpiretime = (time_t)1;
6457 6467          mutex_exit(&assoc->ipsa_lock);
6458 6468  }
6459 6469  
6460 6470  /*
6461 6471   * Special front-end to ipsec_rl_strlog() dealing with SA failure.
6462 6472   * this is designed to take only a format string with "* %x * %s *", so
6463 6473   * that "spi" is printed first, then "addr" is converted using inet_pton().
6464 6474   *
6465 6475   * This is abstracted out to save the stack space for only when inet_pton()
6466 6476   * is called.  Make sure "spi" is in network order; it usually is when this
6467 6477   * would get called.
6468 6478   */
6469 6479  void
6470 6480  ipsec_assocfailure(short mid, short sid, char level, ushort_t sl, char *fmt,
6471 6481      uint32_t spi, void *addr, int af, netstack_t *ns)
6472 6482  {
6473 6483          char buf[INET6_ADDRSTRLEN];
6474 6484  
6475 6485          ASSERT(af == AF_INET6 || af == AF_INET);
6476 6486  
6477 6487          ipsec_rl_strlog(ns, mid, sid, level, sl, fmt, ntohl(spi),
6478 6488              inet_ntop(af, addr, buf, sizeof (buf)));
6479 6489  }
6480 6490  
6481 6491  /*
6482 6492   * Fills in a reference to the policy, if any, from the conn, in *ppp
6483 6493   */
6484 6494  static void
6485 6495  ipsec_conn_pol(ipsec_selector_t *sel, conn_t *connp, ipsec_policy_t **ppp)
6486 6496  {
6487 6497          ipsec_policy_t  *pp;
6488 6498          ipsec_latch_t   *ipl = connp->conn_latch;
6489 6499  
6490 6500          if ((ipl != NULL) && (connp->conn_ixa->ixa_ipsec_policy != NULL)) {
6491 6501                  pp = connp->conn_ixa->ixa_ipsec_policy;
6492 6502                  IPPOL_REFHOLD(pp);
6493 6503          } else {
6494 6504                  pp = ipsec_find_policy(IPSEC_TYPE_OUTBOUND, connp, sel,
6495 6505                      connp->conn_netstack);
6496 6506          }
6497 6507          *ppp = pp;
6498 6508  }
6499 6509  
6500 6510  /*
6501 6511   * The following functions scan through active conn_t structures
6502 6512   * and return a reference to the best-matching policy it can find.
6503 6513   * Caller must release the reference.
6504 6514   */
6505 6515  static void
6506 6516  ipsec_udp_pol(ipsec_selector_t *sel, ipsec_policy_t **ppp, ip_stack_t *ipst)
6507 6517  {
6508 6518          connf_t *connfp;
6509 6519          conn_t *connp = NULL;
6510 6520          ipsec_selector_t portonly;
6511 6521  
6512 6522          bzero((void *)&portonly, sizeof (portonly));
6513 6523  
6514 6524          if (sel->ips_local_port == 0)
6515 6525                  return;
6516 6526  
6517 6527          connfp = &ipst->ips_ipcl_udp_fanout[IPCL_UDP_HASH(sel->ips_local_port,
6518 6528              ipst)];
6519 6529          mutex_enter(&connfp->connf_lock);
6520 6530  
6521 6531          if (sel->ips_isv4) {
6522 6532                  connp = connfp->connf_head;
6523 6533                  while (connp != NULL) {
6524 6534                          if (IPCL_UDP_MATCH(connp, sel->ips_local_port,
6525 6535                              sel->ips_local_addr_v4, sel->ips_remote_port,
6526 6536                              sel->ips_remote_addr_v4))
6527 6537                                  break;
6528 6538                          connp = connp->conn_next;
6529 6539                  }
6530 6540  
6531 6541                  if (connp == NULL) {
6532 6542                          /* Try port-only match in IPv6. */
6533 6543                          portonly.ips_local_port = sel->ips_local_port;
6534 6544                          sel = &portonly;
6535 6545                  }
6536 6546          }
6537 6547  
6538 6548          if (connp == NULL) {
6539 6549                  connp = connfp->connf_head;
6540 6550                  while (connp != NULL) {
6541 6551                          if (IPCL_UDP_MATCH_V6(connp, sel->ips_local_port,
6542 6552                              sel->ips_local_addr_v6, sel->ips_remote_port,
6543 6553                              sel->ips_remote_addr_v6))
6544 6554                                  break;
6545 6555                          connp = connp->conn_next;
6546 6556                  }
6547 6557  
6548 6558                  if (connp == NULL) {
6549 6559                          mutex_exit(&connfp->connf_lock);
6550 6560                          return;
6551 6561                  }
6552 6562          }
6553 6563  
6554 6564          CONN_INC_REF(connp);
6555 6565          mutex_exit(&connfp->connf_lock);
6556 6566  
6557 6567          ipsec_conn_pol(sel, connp, ppp);
6558 6568          CONN_DEC_REF(connp);
6559 6569  }
6560 6570  
6561 6571  static conn_t *
6562 6572  ipsec_find_listen_conn(uint16_t *pptr, ipsec_selector_t *sel, ip_stack_t *ipst)
6563 6573  {
6564 6574          connf_t *connfp;
6565 6575          conn_t *connp = NULL;
6566 6576          const in6_addr_t *v6addrmatch = &sel->ips_local_addr_v6;
6567 6577  
6568 6578          if (sel->ips_local_port == 0)
6569 6579                  return (NULL);
6570 6580  
6571 6581          connfp = &ipst->ips_ipcl_bind_fanout[
6572 6582              IPCL_BIND_HASH(sel->ips_local_port, ipst)];
6573 6583          mutex_enter(&connfp->connf_lock);
6574 6584  
6575 6585          if (sel->ips_isv4) {
6576 6586                  connp = connfp->connf_head;
6577 6587                  while (connp != NULL) {
6578 6588                          if (IPCL_BIND_MATCH(connp, IPPROTO_TCP,
6579 6589                              sel->ips_local_addr_v4, pptr[1]))
6580 6590                                  break;
6581 6591                          connp = connp->conn_next;
6582 6592                  }
6583 6593  
6584 6594                  if (connp == NULL) {
6585 6595                          /* Match to all-zeroes. */
6586 6596                          v6addrmatch = &ipv6_all_zeros;
6587 6597                  }
6588 6598          }
6589 6599  
6590 6600          if (connp == NULL) {
6591 6601                  connp = connfp->connf_head;
6592 6602                  while (connp != NULL) {
6593 6603                          if (IPCL_BIND_MATCH_V6(connp, IPPROTO_TCP,
6594 6604                              *v6addrmatch, pptr[1]))
6595 6605                                  break;
6596 6606                          connp = connp->conn_next;
6597 6607                  }
6598 6608  
6599 6609                  if (connp == NULL) {
6600 6610                          mutex_exit(&connfp->connf_lock);
6601 6611                          return (NULL);
6602 6612                  }
6603 6613          }
6604 6614  
6605 6615          CONN_INC_REF(connp);
6606 6616          mutex_exit(&connfp->connf_lock);
6607 6617          return (connp);
6608 6618  }
6609 6619  
6610 6620  static void
6611 6621  ipsec_tcp_pol(ipsec_selector_t *sel, ipsec_policy_t **ppp, ip_stack_t *ipst)
6612 6622  {
6613 6623          connf_t         *connfp;
6614 6624          conn_t          *connp;
6615 6625          uint32_t        ports;
6616 6626          uint16_t        *pptr = (uint16_t *)&ports;
6617 6627  
6618 6628          /*
6619 6629           * Find TCP state in the following order:
6620 6630           * 1.) Connected conns.
6621 6631           * 2.) Listeners.
6622 6632           *
6623 6633           * Even though #2 will be the common case for inbound traffic, only
6624 6634           * following this order insures correctness.
6625 6635           */
6626 6636  
6627 6637          if (sel->ips_local_port == 0)
6628 6638                  return;
6629 6639  
6630 6640          /*
6631 6641           * 0 should be fport, 1 should be lport.  SRC is the local one here.
6632 6642           * See ipsec_construct_inverse_acquire() for details.
6633 6643           */
6634 6644          pptr[0] = sel->ips_remote_port;
6635 6645          pptr[1] = sel->ips_local_port;
6636 6646  
6637 6647          connfp = &ipst->ips_ipcl_conn_fanout[
6638 6648              IPCL_CONN_HASH(sel->ips_remote_addr_v4, ports, ipst)];
6639 6649          mutex_enter(&connfp->connf_lock);
6640 6650          connp = connfp->connf_head;
6641 6651  
6642 6652          if (sel->ips_isv4) {
6643 6653                  while (connp != NULL) {
6644 6654                          if (IPCL_CONN_MATCH(connp, IPPROTO_TCP,
6645 6655                              sel->ips_remote_addr_v4, sel->ips_local_addr_v4,
6646 6656                              ports))
6647 6657                                  break;
6648 6658                          connp = connp->conn_next;
6649 6659                  }
6650 6660          } else {
6651 6661                  while (connp != NULL) {
6652 6662                          if (IPCL_CONN_MATCH_V6(connp, IPPROTO_TCP,
6653 6663                              sel->ips_remote_addr_v6, sel->ips_local_addr_v6,
6654 6664                              ports))
6655 6665                                  break;
6656 6666                          connp = connp->conn_next;
6657 6667                  }
6658 6668          }
6659 6669  
6660 6670          if (connp != NULL) {
6661 6671                  CONN_INC_REF(connp);
6662 6672                  mutex_exit(&connfp->connf_lock);
6663 6673          } else {
6664 6674                  mutex_exit(&connfp->connf_lock);
6665 6675  
6666 6676                  /* Try the listen hash. */
6667 6677                  if ((connp = ipsec_find_listen_conn(pptr, sel, ipst)) == NULL)
6668 6678                          return;
6669 6679          }
6670 6680  
6671 6681          ipsec_conn_pol(sel, connp, ppp);
6672 6682          CONN_DEC_REF(connp);
6673 6683  }
6674 6684  
6675 6685  static void
6676 6686  ipsec_sctp_pol(ipsec_selector_t *sel, ipsec_policy_t **ppp,
6677 6687      ip_stack_t *ipst)
6678 6688  {
6679 6689          conn_t          *connp;
6680 6690          uint32_t        ports;
6681 6691          uint16_t        *pptr = (uint16_t *)&ports;
6682 6692  
6683 6693          /*
6684 6694           * Find SCP state in the following order:
6685 6695           * 1.) Connected conns.
6686 6696           * 2.) Listeners.
6687 6697           *
6688 6698           * Even though #2 will be the common case for inbound traffic, only
6689 6699           * following this order insures correctness.
6690 6700           */
6691 6701  
6692 6702          if (sel->ips_local_port == 0)
6693 6703                  return;
6694 6704  
6695 6705          /*
6696 6706           * 0 should be fport, 1 should be lport.  SRC is the local one here.
6697 6707           * See ipsec_construct_inverse_acquire() for details.
6698 6708           */
6699 6709          pptr[0] = sel->ips_remote_port;
6700 6710          pptr[1] = sel->ips_local_port;
6701 6711  
6702 6712          /*
6703 6713           * For labeled systems, there's no need to check the
6704 6714           * label here.  It's known to be good as we checked
6705 6715           * before allowing the connection to become bound.
6706 6716           */
6707 6717          if (sel->ips_isv4) {
6708 6718                  in6_addr_t      src, dst;
6709 6719  
6710 6720                  IN6_IPADDR_TO_V4MAPPED(sel->ips_remote_addr_v4, &dst);
6711 6721                  IN6_IPADDR_TO_V4MAPPED(sel->ips_local_addr_v4, &src);
6712 6722                  connp = sctp_find_conn(&dst, &src, ports, ALL_ZONES,
6713 6723                      0, ipst->ips_netstack->netstack_sctp);
6714 6724          } else {
6715 6725                  connp = sctp_find_conn(&sel->ips_remote_addr_v6,
6716 6726                      &sel->ips_local_addr_v6, ports, ALL_ZONES,
6717 6727                      0, ipst->ips_netstack->netstack_sctp);
6718 6728          }
6719 6729          if (connp == NULL)
6720 6730                  return;
6721 6731          ipsec_conn_pol(sel, connp, ppp);
6722 6732          CONN_DEC_REF(connp);
6723 6733  }
6724 6734  
6725 6735  /*
6726 6736   * Fill in a query for the SPD (in "sel") using two PF_KEY address extensions.
6727 6737   * Returns 0 or errno, and always sets *diagnostic to something appropriate
6728 6738   * to PF_KEY.
6729 6739   *
6730 6740   * NOTE:  For right now, this function (and ipsec_selector_t for that matter),
6731 6741   * ignore prefix lengths in the address extension.  Since we match on first-
6732 6742   * entered policies, this shouldn't matter.  Also, since we normalize prefix-
6733 6743   * set addresses to mask out the lower bits, we should get a suitable search
6734 6744   * key for the SPD anyway.  This is the function to change if the assumption
6735 6745   * about suitable search keys is wrong.
6736 6746   */
6737 6747  static int
6738 6748  ipsec_get_inverse_acquire_sel(ipsec_selector_t *sel, sadb_address_t *srcext,
6739 6749      sadb_address_t *dstext, int *diagnostic)
6740 6750  {
6741 6751          struct sockaddr_in *src, *dst;
6742 6752          struct sockaddr_in6 *src6, *dst6;
6743 6753  
6744 6754          *diagnostic = 0;
6745 6755  
6746 6756          bzero(sel, sizeof (*sel));
6747 6757          sel->ips_protocol = srcext->sadb_address_proto;
6748 6758          dst = (struct sockaddr_in *)(dstext + 1);
6749 6759          if (dst->sin_family == AF_INET6) {
6750 6760                  dst6 = (struct sockaddr_in6 *)dst;
6751 6761                  src6 = (struct sockaddr_in6 *)(srcext + 1);
6752 6762                  if (src6->sin6_family != AF_INET6) {
6753 6763                          *diagnostic = SADB_X_DIAGNOSTIC_AF_MISMATCH;
6754 6764                          return (EINVAL);
6755 6765                  }
6756 6766                  sel->ips_remote_addr_v6 = dst6->sin6_addr;
6757 6767                  sel->ips_local_addr_v6 = src6->sin6_addr;
6758 6768                  if (sel->ips_protocol == IPPROTO_ICMPV6) {
6759 6769                          sel->ips_is_icmp_inv_acq = 1;
6760 6770                  } else {
6761 6771                          sel->ips_remote_port = dst6->sin6_port;
6762 6772                          sel->ips_local_port = src6->sin6_port;
6763 6773                  }
6764 6774                  sel->ips_isv4 = B_FALSE;
6765 6775          } else {
6766 6776                  src = (struct sockaddr_in *)(srcext + 1);
6767 6777                  if (src->sin_family != AF_INET) {
6768 6778                          *diagnostic = SADB_X_DIAGNOSTIC_AF_MISMATCH;
6769 6779                          return (EINVAL);
6770 6780                  }
6771 6781                  sel->ips_remote_addr_v4 = dst->sin_addr.s_addr;
6772 6782                  sel->ips_local_addr_v4 = src->sin_addr.s_addr;
6773 6783                  if (sel->ips_protocol == IPPROTO_ICMP) {
6774 6784                          sel->ips_is_icmp_inv_acq = 1;
6775 6785                  } else {
6776 6786                          sel->ips_remote_port = dst->sin_port;
6777 6787                          sel->ips_local_port = src->sin_port;
6778 6788                  }
6779 6789                  sel->ips_isv4 = B_TRUE;
6780 6790          }
6781 6791          return (0);
6782 6792  }
6783 6793  
6784 6794  /*
6785 6795   * We have encapsulation.
6786 6796   * - Lookup tun_t by address and look for an associated
6787 6797   *   tunnel policy
6788 6798   * - If there are inner selectors
6789 6799   *   - check ITPF_P_TUNNEL and ITPF_P_ACTIVE
6790 6800   *   - Look up tunnel policy based on selectors
6791 6801   * - Else
6792 6802   *   - Sanity check the negotation
6793 6803   *   - If appropriate, fall through to global policy
6794 6804   */
6795 6805  static int
6796 6806  ipsec_tun_pol(ipsec_selector_t *sel, ipsec_policy_t **ppp,
6797 6807      sadb_address_t *innsrcext, sadb_address_t *inndstext, ipsec_tun_pol_t *itp,
6798 6808      int *diagnostic)
6799 6809  {
6800 6810          int err;
6801 6811          ipsec_policy_head_t *polhead;
6802 6812  
6803 6813          *diagnostic = 0;
6804 6814  
6805 6815          /* Check for inner selectors and act appropriately */
6806 6816  
6807 6817          if (innsrcext != NULL) {
6808 6818                  /* Inner selectors present */
6809 6819                  ASSERT(inndstext != NULL);
6810 6820                  if ((itp == NULL) ||
6811 6821                      (itp->itp_flags & (ITPF_P_ACTIVE | ITPF_P_TUNNEL)) !=
6812 6822                      (ITPF_P_ACTIVE | ITPF_P_TUNNEL)) {
6813 6823                          /*
6814 6824                           * If inner packet selectors, we must have negotiate
6815 6825                           * tunnel and active policy.  If the tunnel has
6816 6826                           * transport-mode policy set on it, or has no policy,
6817 6827                           * fail.
6818 6828                           */
6819 6829                          return (ENOENT);
6820 6830                  } else {
6821 6831                          /*
6822 6832                           * Reset "sel" to indicate inner selectors.  Pass
6823 6833                           * inner PF_KEY address extensions for this to happen.
6824 6834                           */
6825 6835                          if ((err = ipsec_get_inverse_acquire_sel(sel,
6826 6836                              innsrcext, inndstext, diagnostic)) != 0)
6827 6837                                  return (err);
6828 6838                          /*
6829 6839                           * Now look for a tunnel policy based on those inner
6830 6840                           * selectors.  (Common code is below.)
6831 6841                           */
6832 6842                  }
6833 6843          } else {
6834 6844                  /* No inner selectors present */
6835 6845                  if ((itp == NULL) || !(itp->itp_flags & ITPF_P_ACTIVE)) {
6836 6846                          /*
6837 6847                           * Transport mode negotiation with no tunnel policy
6838 6848                           * configured - return to indicate a global policy
6839 6849                           * check is needed.
6840 6850                           */
6841 6851                          return (0);
6842 6852                  } else if (itp->itp_flags & ITPF_P_TUNNEL) {
6843 6853                          /* Tunnel mode set with no inner selectors. */
6844 6854                          return (ENOENT);
6845 6855                  }
6846 6856                  /*
6847 6857                   * Else, this is a tunnel policy configured with ifconfig(1m)
6848 6858                   * or "negotiate transport" with ipsecconf(1m).  We have an
6849 6859                   * itp with policy set based on any match, so don't bother
6850 6860                   * changing fields in "sel".
6851 6861                   */
6852 6862          }
6853 6863  
6854 6864          ASSERT(itp != NULL);
6855 6865          polhead = itp->itp_policy;
6856 6866          ASSERT(polhead != NULL);
6857 6867          rw_enter(&polhead->iph_lock, RW_READER);
6858 6868          *ppp = ipsec_find_policy_head(NULL, polhead, IPSEC_TYPE_INBOUND, sel);
6859 6869          rw_exit(&polhead->iph_lock);
6860 6870  
6861 6871          /*
6862 6872           * Don't default to global if we didn't find a matching policy entry.
6863 6873           * Instead, send ENOENT, just like if we hit a transport-mode tunnel.
6864 6874           */
6865 6875          if (*ppp == NULL)
6866 6876                  return (ENOENT);
6867 6877  
6868 6878          return (0);
6869 6879  }
6870 6880  
6871 6881  /*
6872 6882   * For sctp conn_faddr is the primary address, hence this is of limited
6873 6883   * use for sctp.
6874 6884   */
6875 6885  static void
6876 6886  ipsec_oth_pol(ipsec_selector_t *sel, ipsec_policy_t **ppp,
6877 6887      ip_stack_t *ipst)
6878 6888  {
6879 6889          boolean_t       isv4 = sel->ips_isv4;
6880 6890          connf_t         *connfp;
6881 6891          conn_t          *connp;
6882 6892  
6883 6893          if (isv4) {
6884 6894                  connfp = &ipst->ips_ipcl_proto_fanout_v4[sel->ips_protocol];
6885 6895          } else {
6886 6896                  connfp = &ipst->ips_ipcl_proto_fanout_v6[sel->ips_protocol];
6887 6897          }
6888 6898  
6889 6899          mutex_enter(&connfp->connf_lock);
6890 6900          for (connp = connfp->connf_head; connp != NULL;
6891 6901              connp = connp->conn_next) {
6892 6902                  if (isv4) {
6893 6903                          if ((connp->conn_laddr_v4 == INADDR_ANY ||
6894 6904                              connp->conn_laddr_v4 == sel->ips_local_addr_v4) &&
6895 6905                              (connp->conn_faddr_v4 == INADDR_ANY ||
6896 6906                              connp->conn_faddr_v4 == sel->ips_remote_addr_v4))
6897 6907                                  break;
6898 6908                  } else {
6899 6909                          if ((IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6) ||
6900 6910                              IN6_ARE_ADDR_EQUAL(&connp->conn_laddr_v6,
6901 6911                              &sel->ips_local_addr_v6)) &&
6902 6912                              (IN6_IS_ADDR_UNSPECIFIED(&connp->conn_faddr_v6) ||
6903 6913                              IN6_ARE_ADDR_EQUAL(&connp->conn_faddr_v6,
6904 6914                              &sel->ips_remote_addr_v6)))
6905 6915                                  break;
6906 6916                  }
6907 6917          }
6908 6918          if (connp == NULL) {
6909 6919                  mutex_exit(&connfp->connf_lock);
6910 6920                  return;
6911 6921          }
6912 6922  
6913 6923          CONN_INC_REF(connp);
6914 6924          mutex_exit(&connfp->connf_lock);
6915 6925  
6916 6926          ipsec_conn_pol(sel, connp, ppp);
6917 6927          CONN_DEC_REF(connp);
6918 6928  }
6919 6929  
6920 6930  /*
6921 6931   * Construct an inverse ACQUIRE reply based on:
6922 6932   *
6923 6933   * 1.) Current global policy.
6924 6934   * 2.) An conn_t match depending on what all was passed in the extv[].
6925 6935   * 3.) A tunnel's policy head.
6926 6936   * ...
6927 6937   * N.) Other stuff TBD (e.g. identities)
6928 6938   *
6929 6939   * If there is an error, set sadb_msg_errno and sadb_x_msg_diagnostic
6930 6940   * in this function so the caller can extract them where appropriately.
6931 6941   *
6932 6942   * The SRC address is the local one - just like an outbound ACQUIRE message.
6933 6943   *
6934 6944   * XXX MLS: key management supplies a label which we just reflect back up
6935 6945   * again.  clearly we need to involve the label in the rest of the checks.
6936 6946   */
6937 6947  mblk_t *
6938 6948  ipsec_construct_inverse_acquire(sadb_msg_t *samsg, sadb_ext_t *extv[],
6939 6949      netstack_t *ns)
6940 6950  {
6941 6951          int err;
6942 6952          int diagnostic;
6943 6953          sadb_address_t *srcext = (sadb_address_t *)extv[SADB_EXT_ADDRESS_SRC],
6944 6954              *dstext = (sadb_address_t *)extv[SADB_EXT_ADDRESS_DST],
6945 6955              *innsrcext = (sadb_address_t *)extv[SADB_X_EXT_ADDRESS_INNER_SRC],
6946 6956              *inndstext = (sadb_address_t *)extv[SADB_X_EXT_ADDRESS_INNER_DST];
6947 6957          sadb_sens_t *sens = (sadb_sens_t *)extv[SADB_EXT_SENSITIVITY];
6948 6958          struct sockaddr_in6 *src, *dst;
6949 6959          struct sockaddr_in6 *isrc, *idst;
6950 6960          ipsec_tun_pol_t *itp = NULL;
6951 6961          ipsec_policy_t *pp = NULL;
6952 6962          ipsec_selector_t sel, isel;
6953 6963          mblk_t *retmp = NULL;
6954 6964          ip_stack_t      *ipst = ns->netstack_ip;
6955 6965  
6956 6966  
6957 6967          /* Normalize addresses */
6958 6968          if (sadb_addrcheck(NULL, (mblk_t *)samsg, (sadb_ext_t *)srcext, 0, ns)
6959 6969              == KS_IN_ADDR_UNKNOWN) {
6960 6970                  err = EINVAL;
6961 6971                  diagnostic = SADB_X_DIAGNOSTIC_BAD_SRC;
6962 6972                  goto bail;
6963 6973          }
6964 6974          src = (struct sockaddr_in6 *)(srcext + 1);
6965 6975          if (sadb_addrcheck(NULL, (mblk_t *)samsg, (sadb_ext_t *)dstext, 0, ns)
6966 6976              == KS_IN_ADDR_UNKNOWN) {
6967 6977                  err = EINVAL;
6968 6978                  diagnostic = SADB_X_DIAGNOSTIC_BAD_DST;
6969 6979                  goto bail;
6970 6980          }
6971 6981          dst = (struct sockaddr_in6 *)(dstext + 1);
6972 6982          if (src->sin6_family != dst->sin6_family) {
6973 6983                  err = EINVAL;
6974 6984                  diagnostic = SADB_X_DIAGNOSTIC_AF_MISMATCH;
6975 6985                  goto bail;
6976 6986          }
6977 6987  
6978 6988          /* Check for tunnel mode and act appropriately */
6979 6989          if (innsrcext != NULL) {
6980 6990                  if (inndstext == NULL) {
6981 6991                          err = EINVAL;
6982 6992                          diagnostic = SADB_X_DIAGNOSTIC_MISSING_INNER_DST;
6983 6993                          goto bail;
6984 6994                  }
6985 6995                  if (sadb_addrcheck(NULL, (mblk_t *)samsg,
6986 6996                      (sadb_ext_t *)innsrcext, 0, ns) == KS_IN_ADDR_UNKNOWN) {
6987 6997                          err = EINVAL;
6988 6998                          diagnostic = SADB_X_DIAGNOSTIC_MALFORMED_INNER_SRC;
6989 6999                          goto bail;
6990 7000                  }
6991 7001                  isrc = (struct sockaddr_in6 *)(innsrcext + 1);
6992 7002                  if (sadb_addrcheck(NULL, (mblk_t *)samsg,
6993 7003                      (sadb_ext_t *)inndstext, 0, ns) == KS_IN_ADDR_UNKNOWN) {
6994 7004                          err = EINVAL;
6995 7005                          diagnostic = SADB_X_DIAGNOSTIC_MALFORMED_INNER_DST;
6996 7006                          goto bail;
6997 7007                  }
6998 7008                  idst = (struct sockaddr_in6 *)(inndstext + 1);
6999 7009                  if (isrc->sin6_family != idst->sin6_family) {
7000 7010                          err = EINVAL;
7001 7011                          diagnostic = SADB_X_DIAGNOSTIC_INNER_AF_MISMATCH;
7002 7012                          goto bail;
7003 7013                  }
7004 7014                  if (isrc->sin6_family != AF_INET &&
7005 7015                      isrc->sin6_family != AF_INET6) {
7006 7016                          err = EINVAL;
7007 7017                          diagnostic = SADB_X_DIAGNOSTIC_BAD_INNER_SRC_AF;
7008 7018                          goto bail;
7009 7019                  }
7010 7020          } else if (inndstext != NULL) {
7011 7021                  err = EINVAL;
7012 7022                  diagnostic = SADB_X_DIAGNOSTIC_MISSING_INNER_SRC;
7013 7023                  goto bail;
7014 7024          }
7015 7025  
7016 7026          /* Get selectors first, based on outer addresses */
7017 7027          err = ipsec_get_inverse_acquire_sel(&sel, srcext, dstext, &diagnostic);
7018 7028          if (err != 0)
7019 7029                  goto bail;
7020 7030  
7021 7031          /* Check for tunnel mode mismatches. */
7022 7032          if (innsrcext != NULL &&
7023 7033              ((isrc->sin6_family == AF_INET &&
7024 7034              sel.ips_protocol != IPPROTO_ENCAP && sel.ips_protocol != 0) ||
7025 7035              (isrc->sin6_family == AF_INET6 &&
7026 7036              sel.ips_protocol != IPPROTO_IPV6 && sel.ips_protocol != 0))) {
7027 7037                  err = EPROTOTYPE;
7028 7038                  goto bail;
7029 7039          }
7030 7040  
7031 7041          /*
7032 7042           * Okay, we have the addresses and other selector information.
7033 7043           * Let's first find a conn...
7034 7044           */
7035 7045          pp = NULL;
7036 7046          switch (sel.ips_protocol) {
7037 7047          case IPPROTO_TCP:
7038 7048                  ipsec_tcp_pol(&sel, &pp, ipst);
7039 7049                  break;
7040 7050          case IPPROTO_UDP:
7041 7051                  ipsec_udp_pol(&sel, &pp, ipst);
7042 7052                  break;
7043 7053          case IPPROTO_SCTP:
7044 7054                  ipsec_sctp_pol(&sel, &pp, ipst);
7045 7055                  break;
7046 7056          case IPPROTO_ENCAP:
7047 7057          case IPPROTO_IPV6:
7048 7058                  /*
7049 7059                   * Assume sel.ips_remote_addr_* has the right address at
7050 7060                   * that exact position.
7051 7061                   */
7052 7062                  itp = itp_get_byaddr((uint32_t *)(&sel.ips_local_addr_v6),
7053 7063                      (uint32_t *)(&sel.ips_remote_addr_v6), src->sin6_family,
7054 7064                      ipst);
7055 7065  
7056 7066                  if (innsrcext == NULL) {
7057 7067                          /*
7058 7068                           * Transport-mode tunnel, make sure we fake out isel
7059 7069                           * to contain something based on the outer protocol.
7060 7070                           */
7061 7071                          bzero(&isel, sizeof (isel));
7062 7072                          isel.ips_isv4 = (sel.ips_protocol == IPPROTO_ENCAP);
7063 7073                  } /* Else isel is initialized by ipsec_tun_pol(). */
7064 7074                  err = ipsec_tun_pol(&isel, &pp, innsrcext, inndstext, itp,
7065 7075                      &diagnostic);
7066 7076                  /*
7067 7077                   * NOTE:  isel isn't used for now, but in RFC 430x IPsec, it
7068 7078                   * may be.
7069 7079                   */
7070 7080                  if (err != 0)
7071 7081                          goto bail;
7072 7082                  break;
7073 7083          default:
7074 7084                  ipsec_oth_pol(&sel, &pp, ipst);
7075 7085                  break;
7076 7086          }
7077 7087  
7078 7088          /*
7079 7089           * If we didn't find a matching conn_t or other policy head, take a
7080 7090           * look in the global policy.
7081 7091           */
7082 7092          if (pp == NULL) {
7083 7093                  pp = ipsec_find_policy(IPSEC_TYPE_OUTBOUND, NULL, &sel, ns);
7084 7094                  if (pp == NULL) {
7085 7095                          /* There's no global policy. */
7086 7096                          err = ENOENT;
7087 7097                          diagnostic = 0;
7088 7098                          goto bail;
7089 7099                  }
7090 7100          }
7091 7101  
7092 7102          ASSERT(pp != NULL);
7093 7103          retmp = sadb_acquire_msg_base(0, 0, samsg->sadb_msg_seq,
7094 7104              samsg->sadb_msg_pid);
7095 7105          if (retmp != NULL) {
7096 7106                  /* Remove KEYSOCK_OUT, because caller constructs it instead. */
7097 7107                  mblk_t *kso = retmp;
7098 7108  
7099 7109                  retmp = retmp->b_cont;
7100 7110                  freeb(kso);
7101 7111                  /* Append addresses... */
7102 7112                  retmp->b_cont = sadb_acquire_msg_common(&sel, pp, NULL,
7103 7113                      (itp != NULL && (itp->itp_flags & ITPF_P_TUNNEL)), NULL,
7104 7114                      sens);
7105 7115                  if (retmp->b_cont == NULL) {
7106 7116                          freemsg(retmp);
7107 7117                          retmp = NULL;
7108 7118                  }
7109 7119                  /* And the policy result. */
7110 7120                  retmp->b_cont->b_cont =
7111 7121                      sadb_acquire_extended_prop(pp->ipsp_act, ns);
7112 7122                  if (retmp->b_cont->b_cont == NULL) {
7113 7123                          freemsg(retmp);
7114 7124                          retmp = NULL;
7115 7125                  }
7116 7126                  ((sadb_msg_t *)retmp->b_rptr)->sadb_msg_len =
7117 7127                      SADB_8TO64(msgsize(retmp));
7118 7128          }
7119 7129  
7120 7130          if (pp != NULL) {
7121 7131                  IPPOL_REFRELE(pp);
7122 7132          }
7123 7133          ASSERT(err == 0 && diagnostic == 0);
7124 7134          if (retmp == NULL)
7125 7135                  err = ENOMEM;
7126 7136  bail:
7127 7137          if (itp != NULL) {
7128 7138                  ITP_REFRELE(itp, ns);
7129 7139          }
7130 7140          samsg->sadb_msg_errno = (uint8_t)err;
7131 7141          samsg->sadb_x_msg_diagnostic = (uint16_t)diagnostic;
7132 7142          return (retmp);
7133 7143  }
7134 7144  
7135 7145  /*
7136 7146   * ipsa_lpkt is a one-element queue, only manipulated by the next two
7137 7147   * functions.  They have to hold the ipsa_lock because of potential races
7138 7148   * between key management using SADB_UPDATE, and inbound packets that may
7139 7149   * queue up on the larval SA (hence the 'l' in "lpkt").
7140 7150   */
7141 7151  
7142 7152  /*
7143 7153   * sadb_set_lpkt:
7144 7154   *
7145 7155   * Returns the passed-in packet if the SA is no longer larval.
7146 7156   *
7147 7157   * Returns NULL if the SA is larval, and needs to be swapped into the SA for
7148 7158   * processing after an SADB_UPDATE.
7149 7159   */
7150 7160  mblk_t *
7151 7161  sadb_set_lpkt(ipsa_t *ipsa, mblk_t *npkt, ip_recv_attr_t *ira)
7152 7162  {
7153 7163          mblk_t          *opkt;
7154 7164  
7155 7165          mutex_enter(&ipsa->ipsa_lock);
7156 7166          opkt = ipsa->ipsa_lpkt;
7157 7167          if (ipsa->ipsa_state == IPSA_STATE_LARVAL) {
7158 7168                  /*
7159 7169                   * Consume npkt and place it in the LARVAL SA's inbound
7160 7170                   * packet slot.
7161 7171                   */
7162 7172                  mblk_t  *attrmp;
7163 7173  
7164 7174                  attrmp = ip_recv_attr_to_mblk(ira);
7165 7175                  if (attrmp == NULL) {
7166 7176                          ill_t *ill = ira->ira_ill;
7167 7177  
7168 7178                          BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards);
7169 7179                          ip_drop_input("ipIfStatsInDiscards", npkt, ill);
7170 7180                          freemsg(npkt);
7171 7181                          opkt = NULL;
7172 7182                  } else {
7173 7183                          ASSERT(attrmp->b_cont == NULL);
7174 7184                          attrmp->b_cont = npkt;
7175 7185                          ipsa->ipsa_lpkt = attrmp;
7176 7186                  }
7177 7187                  npkt = NULL;
7178 7188          } else {
7179 7189                  /*
7180 7190                   * If not larval, we lost the race.  NOTE: ipsa_lpkt may still
7181 7191                   * have been non-NULL in the non-larval case, because of
7182 7192                   * inbound packets arriving prior to sadb_common_add()
7183 7193                   * transferring the SA completely out of larval state, but
7184 7194                   * after lpkt was grabbed by the AH/ESP-specific add routines.
7185 7195                   * We should clear the old ipsa_lpkt in this case to make sure
7186 7196                   * that it doesn't linger on the now-MATURE IPsec SA, or get
7187 7197                   * picked up as an out-of-order packet.
7188 7198                   */
7189 7199                  ipsa->ipsa_lpkt = NULL;
7190 7200          }
7191 7201          mutex_exit(&ipsa->ipsa_lock);
7192 7202  
7193 7203          if (opkt != NULL) {
7194 7204                  ipsec_stack_t   *ipss;
7195 7205  
7196 7206                  ipss = ira->ira_ill->ill_ipst->ips_netstack->netstack_ipsec;
7197 7207                  opkt = ip_recv_attr_free_mblk(opkt);
7198 7208                  ip_drop_packet(opkt, B_TRUE, ira->ira_ill,
7199 7209                      DROPPER(ipss, ipds_sadb_inlarval_replace),
7200 7210                      &ipss->ipsec_sadb_dropper);
7201 7211          }
7202 7212          return (npkt);
7203 7213  }
7204 7214  
7205 7215  /*
7206 7216   * sadb_clear_lpkt: Atomically clear ipsa->ipsa_lpkt and return the
7207 7217   * previous value.
7208 7218   */
7209 7219  mblk_t *
7210 7220  sadb_clear_lpkt(ipsa_t *ipsa)
7211 7221  {
7212 7222          mblk_t *opkt;
7213 7223  
7214 7224          mutex_enter(&ipsa->ipsa_lock);
7215 7225          opkt = ipsa->ipsa_lpkt;
7216 7226          ipsa->ipsa_lpkt = NULL;
7217 7227          mutex_exit(&ipsa->ipsa_lock);
7218 7228          return (opkt);
7219 7229  }
7220 7230  
7221 7231  /*
7222 7232   * Buffer a packet that's in IDLE state as set by Solaris Clustering.
7223 7233   */
7224 7234  void
7225 7235  sadb_buf_pkt(ipsa_t *ipsa, mblk_t *bpkt, ip_recv_attr_t *ira)
7226 7236  {
7227 7237          netstack_t      *ns = ira->ira_ill->ill_ipst->ips_netstack;
7228 7238          ipsec_stack_t   *ipss = ns->netstack_ipsec;
7229 7239          in6_addr_t *srcaddr = (in6_addr_t *)(&ipsa->ipsa_srcaddr);
7230 7240          in6_addr_t *dstaddr = (in6_addr_t *)(&ipsa->ipsa_dstaddr);
7231 7241          mblk_t          *mp;
7232 7242  
7233 7243          ASSERT(ipsa->ipsa_state == IPSA_STATE_IDLE);
7234 7244  
7235 7245          if (cl_inet_idlesa == NULL) {
7236 7246                  ip_drop_packet(bpkt, B_TRUE, ira->ira_ill,
7237 7247                      DROPPER(ipss, ipds_sadb_inidle_overflow),
7238 7248                      &ipss->ipsec_sadb_dropper);
7239 7249                  return;
7240 7250          }
7241 7251  
7242 7252          cl_inet_idlesa(ns->netstack_stackid,
7243 7253              (ipsa->ipsa_type == SADB_SATYPE_AH) ? IPPROTO_AH : IPPROTO_ESP,
7244 7254              ipsa->ipsa_spi, ipsa->ipsa_addrfam, *srcaddr, *dstaddr, NULL);
7245 7255  
7246 7256          mp = ip_recv_attr_to_mblk(ira);
7247 7257          if (mp == NULL) {
7248 7258                  ip_drop_packet(bpkt, B_TRUE, ira->ira_ill,
7249 7259                      DROPPER(ipss, ipds_sadb_inidle_overflow),
7250 7260                      &ipss->ipsec_sadb_dropper);
7251 7261                  return;
7252 7262          }
7253 7263          linkb(mp, bpkt);
7254 7264  
7255 7265          mutex_enter(&ipsa->ipsa_lock);
7256 7266          ipsa->ipsa_mblkcnt++;
7257 7267          if (ipsa->ipsa_bpkt_head == NULL) {
7258 7268                  ipsa->ipsa_bpkt_head = ipsa->ipsa_bpkt_tail = bpkt;
7259 7269          } else {
7260 7270                  ipsa->ipsa_bpkt_tail->b_next = bpkt;
7261 7271                  ipsa->ipsa_bpkt_tail = bpkt;
7262 7272                  if (ipsa->ipsa_mblkcnt > SADB_MAX_IDLEPKTS) {
7263 7273                          mblk_t *tmp;
7264 7274  
7265 7275                          tmp = ipsa->ipsa_bpkt_head;
7266 7276                          ipsa->ipsa_bpkt_head = ipsa->ipsa_bpkt_head->b_next;
7267 7277                          tmp = ip_recv_attr_free_mblk(tmp);
7268 7278                          ip_drop_packet(tmp, B_TRUE, NULL,
7269 7279                              DROPPER(ipss, ipds_sadb_inidle_overflow),
7270 7280                              &ipss->ipsec_sadb_dropper);
7271 7281                          ipsa->ipsa_mblkcnt --;
7272 7282                  }
7273 7283          }
7274 7284          mutex_exit(&ipsa->ipsa_lock);
7275 7285  }
7276 7286  
7277 7287  /*
7278 7288   * Stub function that taskq_dispatch() invokes to take the mblk (in arg)
7279 7289   * and put into STREAMS again.
7280 7290   */
7281 7291  void
7282 7292  sadb_clear_buf_pkt(void *ipkt)
7283 7293  {
7284 7294          mblk_t  *tmp, *buf_pkt;
7285 7295          ip_recv_attr_t  iras;
7286 7296  
7287 7297          buf_pkt = (mblk_t *)ipkt;
7288 7298  
7289 7299          while (buf_pkt != NULL) {
7290 7300                  mblk_t *data_mp;
7291 7301  
7292 7302                  tmp = buf_pkt->b_next;
7293 7303                  buf_pkt->b_next = NULL;
7294 7304  
7295 7305                  data_mp = buf_pkt->b_cont;
7296 7306                  buf_pkt->b_cont = NULL;
7297 7307                  if (!ip_recv_attr_from_mblk(buf_pkt, &iras)) {
7298 7308                          /* The ill or ip_stack_t disappeared on us. */
7299 7309                          ip_drop_input("ip_recv_attr_from_mblk", data_mp, NULL);
7300 7310                          freemsg(data_mp);
7301 7311                  } else {
7302 7312                          ip_input_post_ipsec(data_mp, &iras);
7303 7313                  }
7304 7314                  ira_cleanup(&iras, B_TRUE);
7305 7315                  buf_pkt = tmp;
7306 7316          }
7307 7317  }
7308 7318  /*
7309 7319   * Walker callback used by sadb_alg_update() to free/create crypto
7310 7320   * context template when a crypto software provider is removed or
7311 7321   * added.
7312 7322   */
7313 7323  
7314 7324  struct sadb_update_alg_state {
7315 7325          ipsec_algtype_t alg_type;
7316 7326          uint8_t alg_id;
7317 7327          boolean_t is_added;
7318 7328          boolean_t async_auth;
7319 7329          boolean_t async_encr;
7320 7330  };
7321 7331  
7322 7332  static void
7323 7333  sadb_alg_update_cb(isaf_t *head, ipsa_t *entry, void *cookie)
7324 7334  {
7325 7335          struct sadb_update_alg_state *update_state =
7326 7336              (struct sadb_update_alg_state *)cookie;
7327 7337          crypto_ctx_template_t *ctx_tmpl = NULL;
7328 7338  
7329 7339          ASSERT(MUTEX_HELD(&head->isaf_lock));
7330 7340  
7331 7341          if (entry->ipsa_state == IPSA_STATE_LARVAL)
7332 7342                  return;
7333 7343  
7334 7344          mutex_enter(&entry->ipsa_lock);
7335 7345  
7336 7346          if ((entry->ipsa_encr_alg != SADB_EALG_NONE && entry->ipsa_encr_alg !=
7337 7347              SADB_EALG_NULL && update_state->async_encr) ||
7338 7348              (entry->ipsa_auth_alg != SADB_AALG_NONE &&
7339 7349              update_state->async_auth)) {
7340 7350                  entry->ipsa_flags |= IPSA_F_ASYNC;
7341 7351          } else {
7342 7352                  entry->ipsa_flags &= ~IPSA_F_ASYNC;
7343 7353          }
7344 7354  
7345 7355          switch (update_state->alg_type) {
7346 7356          case IPSEC_ALG_AUTH:
7347 7357                  if (entry->ipsa_auth_alg == update_state->alg_id)
7348 7358                          ctx_tmpl = &entry->ipsa_authtmpl;
7349 7359                  break;
7350 7360          case IPSEC_ALG_ENCR:
7351 7361                  if (entry->ipsa_encr_alg == update_state->alg_id)
7352 7362                          ctx_tmpl = &entry->ipsa_encrtmpl;
7353 7363                  break;
7354 7364          default:
7355 7365                  ctx_tmpl = NULL;
7356 7366          }
7357 7367  
7358 7368          if (ctx_tmpl == NULL) {
7359 7369                  mutex_exit(&entry->ipsa_lock);
7360 7370                  return;
7361 7371          }
7362 7372  
7363 7373          /*
7364 7374           * The context template of the SA may be affected by the change
7365 7375           * of crypto provider.
7366 7376           */
7367 7377          if (update_state->is_added) {
7368 7378                  /* create the context template if not already done */
7369 7379                  if (*ctx_tmpl == NULL) {
7370 7380                          (void) ipsec_create_ctx_tmpl(entry,
7371 7381                              update_state->alg_type);
7372 7382                  }
7373 7383          } else {
7374 7384                  /*
7375 7385                   * The crypto provider was removed. If the context template
7376 7386                   * exists but it is no longer valid, free it.
7377 7387                   */
7378 7388                  if (*ctx_tmpl != NULL)
7379 7389                          ipsec_destroy_ctx_tmpl(entry, update_state->alg_type);
7380 7390          }
7381 7391  
7382 7392          mutex_exit(&entry->ipsa_lock);
7383 7393  }
7384 7394  
7385 7395  /*
7386 7396   * Invoked by IP when an software crypto provider has been updated, or if
7387 7397   * the crypto synchrony changes.  The type and id of the corresponding
7388 7398   * algorithm is passed as argument.  The type is set to ALL in the case of
7389 7399   * a synchrony change.
7390 7400   *
7391 7401   * is_added is B_TRUE if the provider was added, B_FALSE if it was
7392 7402   * removed. The function updates the SADB and free/creates the
7393 7403   * context templates associated with SAs if needed.
7394 7404   */
7395 7405  
7396 7406  #define SADB_ALG_UPDATE_WALK(sadb, table) \
7397 7407      sadb_walker((sadb).table, (sadb).sdb_hashsize, sadb_alg_update_cb, \
7398 7408          &update_state)
7399 7409  
7400 7410  void
7401 7411  sadb_alg_update(ipsec_algtype_t alg_type, uint8_t alg_id, boolean_t is_added,
7402 7412      netstack_t *ns)
7403 7413  {
7404 7414          struct sadb_update_alg_state update_state;
7405 7415          ipsecah_stack_t *ahstack = ns->netstack_ipsecah;
7406 7416          ipsecesp_stack_t        *espstack = ns->netstack_ipsecesp;
7407 7417          ipsec_stack_t *ipss = ns->netstack_ipsec;
7408 7418  
7409 7419          update_state.alg_type = alg_type;
7410 7420          update_state.alg_id = alg_id;
7411 7421          update_state.is_added = is_added;
7412 7422          update_state.async_auth = ipss->ipsec_algs_exec_mode[IPSEC_ALG_AUTH] ==
7413 7423              IPSEC_ALGS_EXEC_ASYNC;
7414 7424          update_state.async_encr = ipss->ipsec_algs_exec_mode[IPSEC_ALG_ENCR] ==
7415 7425              IPSEC_ALGS_EXEC_ASYNC;
7416 7426  
7417 7427          if (alg_type == IPSEC_ALG_AUTH || alg_type == IPSEC_ALG_ALL) {
7418 7428                  /* walk the AH tables only for auth. algorithm changes */
7419 7429                  SADB_ALG_UPDATE_WALK(ahstack->ah_sadb.s_v4, sdb_of);
7420 7430                  SADB_ALG_UPDATE_WALK(ahstack->ah_sadb.s_v4, sdb_if);
7421 7431                  SADB_ALG_UPDATE_WALK(ahstack->ah_sadb.s_v6, sdb_of);
7422 7432                  SADB_ALG_UPDATE_WALK(ahstack->ah_sadb.s_v6, sdb_if);
7423 7433          }
7424 7434  
7425 7435          /* walk the ESP tables */
7426 7436          SADB_ALG_UPDATE_WALK(espstack->esp_sadb.s_v4, sdb_of);
7427 7437          SADB_ALG_UPDATE_WALK(espstack->esp_sadb.s_v4, sdb_if);
7428 7438          SADB_ALG_UPDATE_WALK(espstack->esp_sadb.s_v6, sdb_of);
7429 7439          SADB_ALG_UPDATE_WALK(espstack->esp_sadb.s_v6, sdb_if);
7430 7440  }
7431 7441  
7432 7442  /*
7433 7443   * Creates a context template for the specified SA. This function
7434 7444   * is called when an SA is created and when a context template needs
7435 7445   * to be created due to a change of software provider.
7436 7446   */
7437 7447  int
7438 7448  ipsec_create_ctx_tmpl(ipsa_t *sa, ipsec_algtype_t alg_type)
7439 7449  {
7440 7450          ipsec_alginfo_t *alg;
7441 7451          crypto_mechanism_t mech;
7442 7452          crypto_key_t *key;
7443 7453          crypto_ctx_template_t *sa_tmpl;
7444 7454          int rv;
7445 7455          ipsec_stack_t   *ipss = sa->ipsa_netstack->netstack_ipsec;
7446 7456  
7447 7457          ASSERT(RW_READ_HELD(&ipss->ipsec_alg_lock));
7448 7458          ASSERT(MUTEX_HELD(&sa->ipsa_lock));
7449 7459  
7450 7460          /* get pointers to the algorithm info, context template, and key */
7451 7461          switch (alg_type) {
7452 7462          case IPSEC_ALG_AUTH:
7453 7463                  key = &sa->ipsa_kcfauthkey;
7454 7464                  sa_tmpl = &sa->ipsa_authtmpl;
7455 7465                  alg = ipss->ipsec_alglists[alg_type][sa->ipsa_auth_alg];
7456 7466                  break;
7457 7467          case IPSEC_ALG_ENCR:
7458 7468                  key = &sa->ipsa_kcfencrkey;
7459 7469                  sa_tmpl = &sa->ipsa_encrtmpl;
7460 7470                  alg = ipss->ipsec_alglists[alg_type][sa->ipsa_encr_alg];
7461 7471                  break;
7462 7472          default:
7463 7473                  alg = NULL;
7464 7474          }
7465 7475  
7466 7476          if (alg == NULL || !ALG_VALID(alg))
7467 7477                  return (EINVAL);
7468 7478  
7469 7479          /* initialize the mech info structure for the framework */
7470 7480          ASSERT(alg->alg_mech_type != CRYPTO_MECHANISM_INVALID);
7471 7481          mech.cm_type = alg->alg_mech_type;
7472 7482          mech.cm_param = NULL;
7473 7483          mech.cm_param_len = 0;
7474 7484  
7475 7485          /* create a new context template */
7476 7486          rv = crypto_create_ctx_template(&mech, key, sa_tmpl, KM_NOSLEEP);
7477 7487  
7478 7488          /*
7479 7489           * CRYPTO_MECH_NOT_SUPPORTED can be returned if only hardware
7480 7490           * providers are available for that mechanism. In that case
7481 7491           * we don't fail, and will generate the context template from
7482 7492           * the framework callback when a software provider for that
7483 7493           * mechanism registers.
7484 7494           *
7485 7495           * The context template is assigned the special value
7486 7496           * IPSEC_CTX_TMPL_ALLOC if the allocation failed due to a
7487 7497           * lack of memory. No attempt will be made to use
7488 7498           * the context template if it is set to this value.
7489 7499           */
7490 7500          if (rv == CRYPTO_HOST_MEMORY) {
7491 7501                  *sa_tmpl = IPSEC_CTX_TMPL_ALLOC;
7492 7502          } else if (rv != CRYPTO_SUCCESS) {
7493 7503                  *sa_tmpl = NULL;
7494 7504                  if (rv != CRYPTO_MECH_NOT_SUPPORTED)
7495 7505                          return (EINVAL);
7496 7506          }
7497 7507  
7498 7508          return (0);
7499 7509  }
7500 7510  
7501 7511  /*
7502 7512   * Destroy the context template of the specified algorithm type
7503 7513   * of the specified SA. Must be called while holding the SA lock.
7504 7514   */
7505 7515  void
7506 7516  ipsec_destroy_ctx_tmpl(ipsa_t *sa, ipsec_algtype_t alg_type)
7507 7517  {
7508 7518          ASSERT(MUTEX_HELD(&sa->ipsa_lock));
7509 7519  
7510 7520          if (alg_type == IPSEC_ALG_AUTH) {
7511 7521                  if (sa->ipsa_authtmpl == IPSEC_CTX_TMPL_ALLOC)
7512 7522                          sa->ipsa_authtmpl = NULL;
7513 7523                  else if (sa->ipsa_authtmpl != NULL) {
7514 7524                          crypto_destroy_ctx_template(sa->ipsa_authtmpl);
7515 7525                          sa->ipsa_authtmpl = NULL;
7516 7526                  }
7517 7527          } else {
7518 7528                  ASSERT(alg_type == IPSEC_ALG_ENCR);
7519 7529                  if (sa->ipsa_encrtmpl == IPSEC_CTX_TMPL_ALLOC)
7520 7530                          sa->ipsa_encrtmpl = NULL;
7521 7531                  else if (sa->ipsa_encrtmpl != NULL) {
7522 7532                          crypto_destroy_ctx_template(sa->ipsa_encrtmpl);
7523 7533                          sa->ipsa_encrtmpl = NULL;
7524 7534                  }
7525 7535          }
7526 7536  }
7527 7537  
7528 7538  /*
7529 7539   * Use the kernel crypto framework to check the validity of a key received
7530 7540   * via keysock. Returns 0 if the key is OK, -1 otherwise.
7531 7541   */
7532 7542  int
7533 7543  ipsec_check_key(crypto_mech_type_t mech_type, sadb_key_t *sadb_key,
7534 7544      boolean_t is_auth, int *diag)
7535 7545  {
7536 7546          crypto_mechanism_t mech;
7537 7547          crypto_key_t crypto_key;
7538 7548          int crypto_rc;
7539 7549  
7540 7550          mech.cm_type = mech_type;
7541 7551          mech.cm_param = NULL;
7542 7552          mech.cm_param_len = 0;
7543 7553  
7544 7554          crypto_key.ck_format = CRYPTO_KEY_RAW;
7545 7555          crypto_key.ck_data = sadb_key + 1;
7546 7556          crypto_key.ck_length = sadb_key->sadb_key_bits;
7547 7557  
7548 7558          crypto_rc = crypto_key_check(&mech, &crypto_key);
7549 7559  
7550 7560          switch (crypto_rc) {
7551 7561          case CRYPTO_SUCCESS:
7552 7562                  return (0);
7553 7563          case CRYPTO_MECHANISM_INVALID:
7554 7564          case CRYPTO_MECH_NOT_SUPPORTED:
7555 7565                  *diag = is_auth ? SADB_X_DIAGNOSTIC_BAD_AALG :
7556 7566                      SADB_X_DIAGNOSTIC_BAD_EALG;
7557 7567                  break;
7558 7568          case CRYPTO_KEY_SIZE_RANGE:
7559 7569                  *diag = is_auth ? SADB_X_DIAGNOSTIC_BAD_AKEYBITS :
7560 7570                      SADB_X_DIAGNOSTIC_BAD_EKEYBITS;
7561 7571                  break;
7562 7572          case CRYPTO_WEAK_KEY:
7563 7573                  *diag = is_auth ? SADB_X_DIAGNOSTIC_WEAK_AKEY :
7564 7574                      SADB_X_DIAGNOSTIC_WEAK_EKEY;
7565 7575                  break;
7566 7576          }
7567 7577  
7568 7578          return (-1);
7569 7579  }
7570 7580  
7571 7581  /*
7572 7582   * Whack options in the outer IP header when ipsec changes the outer label
7573 7583   *
7574 7584   * This is inelegant and really could use refactoring.
7575 7585   */
7576 7586  mblk_t *
7577 7587  sadb_whack_label_v4(mblk_t *mp, ipsa_t *assoc, kstat_named_t *counter,
7578 7588      ipdropper_t *dropper)
7579 7589  {
7580 7590          int delta;
7581 7591          int plen;
7582 7592          dblk_t *db;
7583 7593          int hlen;
7584 7594          uint8_t *opt_storage = assoc->ipsa_opt_storage;
7585 7595          ipha_t *ipha = (ipha_t *)mp->b_rptr;
7586 7596  
7587 7597          plen = ntohs(ipha->ipha_length);
7588 7598  
7589 7599          delta = tsol_remove_secopt(ipha, MBLKL(mp));
7590 7600          mp->b_wptr += delta;
7591 7601          plen += delta;
7592 7602  
7593 7603          /* XXX XXX code copied from tsol_check_label */
7594 7604  
7595 7605          /* Make sure we have room for the worst-case addition */
7596 7606          hlen = IPH_HDR_LENGTH(ipha) + opt_storage[IPOPT_OLEN];
7597 7607          hlen = (hlen + 3) & ~3;
7598 7608          if (hlen > IP_MAX_HDR_LENGTH)
7599 7609                  hlen = IP_MAX_HDR_LENGTH;
7600 7610          hlen -= IPH_HDR_LENGTH(ipha);
7601 7611  
7602 7612          db = mp->b_datap;
7603 7613          if ((db->db_ref != 1) || (mp->b_wptr + hlen > db->db_lim)) {
7604 7614                  int copylen;
7605 7615                  mblk_t *new_mp;
7606 7616  
7607 7617                  /* allocate enough to be meaningful, but not *too* much */
7608 7618                  copylen = MBLKL(mp);
7609 7619                  if (copylen > 256)
7610 7620                          copylen = 256;
7611 7621                  new_mp = allocb_tmpl(hlen + copylen +
7612 7622                      (mp->b_rptr - mp->b_datap->db_base), mp);
7613 7623  
7614 7624                  if (new_mp == NULL) {
7615 7625                          ip_drop_packet(mp, B_FALSE, NULL, counter,  dropper);
7616 7626                          return (NULL);
7617 7627                  }
7618 7628  
7619 7629                  /* keep the bias */
7620 7630                  new_mp->b_rptr += mp->b_rptr - mp->b_datap->db_base;
7621 7631                  new_mp->b_wptr = new_mp->b_rptr + copylen;
7622 7632                  bcopy(mp->b_rptr, new_mp->b_rptr, copylen);
7623 7633                  new_mp->b_cont = mp;
7624 7634                  if ((mp->b_rptr += copylen) >= mp->b_wptr) {
7625 7635                          new_mp->b_cont = mp->b_cont;
7626 7636                          freeb(mp);
7627 7637                  }
7628 7638                  mp = new_mp;
7629 7639                  ipha = (ipha_t *)mp->b_rptr;
7630 7640          }
7631 7641  
7632 7642          delta = tsol_prepend_option(assoc->ipsa_opt_storage, ipha, MBLKL(mp));
7633 7643  
7634 7644          ASSERT(delta != -1);
7635 7645  
7636 7646          plen += delta;
7637 7647          mp->b_wptr += delta;
7638 7648  
7639 7649          /*
7640 7650           * Paranoia
7641 7651           */
7642 7652          db = mp->b_datap;
7643 7653  
7644 7654          ASSERT3P(mp->b_wptr, <=, db->db_lim);
7645 7655          ASSERT3P(mp->b_rptr, <=, db->db_lim);
7646 7656  
7647 7657          ASSERT3P(mp->b_wptr, >=, db->db_base);
7648 7658          ASSERT3P(mp->b_rptr, >=, db->db_base);
7649 7659          /* End paranoia */
7650 7660  
7651 7661          ipha->ipha_length = htons(plen);
7652 7662  
7653 7663          return (mp);
7654 7664  }
7655 7665  
7656 7666  mblk_t *
7657 7667  sadb_whack_label_v6(mblk_t *mp, ipsa_t *assoc, kstat_named_t *counter,
7658 7668      ipdropper_t *dropper)
7659 7669  {
7660 7670          int delta;
7661 7671          int plen;
7662 7672          dblk_t *db;
7663 7673          int hlen;
7664 7674          uint8_t *opt_storage = assoc->ipsa_opt_storage;
7665 7675          uint_t sec_opt_len; /* label option length not including type, len */
7666 7676          ip6_t *ip6h = (ip6_t *)mp->b_rptr;
7667 7677  
7668 7678          plen = ntohs(ip6h->ip6_plen);
7669 7679  
7670 7680          delta = tsol_remove_secopt_v6(ip6h, MBLKL(mp));
7671 7681          mp->b_wptr += delta;
7672 7682          plen += delta;
7673 7683  
7674 7684          /* XXX XXX code copied from tsol_check_label_v6 */
7675 7685          /*
7676 7686           * Make sure we have room for the worst-case addition. Add 2 bytes for
7677 7687           * the hop-by-hop ext header's next header and length fields. Add
7678 7688           * another 2 bytes for the label option type, len and then round
7679 7689           * up to the next 8-byte multiple.
7680 7690           */
7681 7691          sec_opt_len = opt_storage[1];
7682 7692  
7683 7693          db = mp->b_datap;
7684 7694          hlen = (4 + sec_opt_len + 7) & ~7;
7685 7695  
7686 7696          if ((db->db_ref != 1) || (mp->b_wptr + hlen > db->db_lim)) {
7687 7697                  int copylen;
7688 7698                  mblk_t *new_mp;
7689 7699                  uint16_t hdr_len;
7690 7700  
7691 7701                  hdr_len = ip_hdr_length_v6(mp, ip6h);
7692 7702                  /*
7693 7703                   * Allocate enough to be meaningful, but not *too* much.
7694 7704                   * Also all the IPv6 extension headers must be in the same mblk
7695 7705                   */
7696 7706                  copylen = MBLKL(mp);
7697 7707                  if (copylen > 256)
7698 7708                          copylen = 256;
7699 7709                  if (copylen < hdr_len)
7700 7710                          copylen = hdr_len;
7701 7711                  new_mp = allocb_tmpl(hlen + copylen +
7702 7712                      (mp->b_rptr - mp->b_datap->db_base), mp);
7703 7713                  if (new_mp == NULL) {
7704 7714                          ip_drop_packet(mp, B_FALSE, NULL, counter,  dropper);
7705 7715                          return (NULL);
7706 7716                  }
7707 7717  
7708 7718                  /* keep the bias */
7709 7719                  new_mp->b_rptr += mp->b_rptr - mp->b_datap->db_base;
7710 7720                  new_mp->b_wptr = new_mp->b_rptr + copylen;
7711 7721                  bcopy(mp->b_rptr, new_mp->b_rptr, copylen);
7712 7722                  new_mp->b_cont = mp;
7713 7723                  if ((mp->b_rptr += copylen) >= mp->b_wptr) {
7714 7724                          new_mp->b_cont = mp->b_cont;
7715 7725                          freeb(mp);
7716 7726                  }
7717 7727                  mp = new_mp;
7718 7728                  ip6h = (ip6_t *)mp->b_rptr;
7719 7729          }
7720 7730  
7721 7731          delta = tsol_prepend_option_v6(assoc->ipsa_opt_storage,
7722 7732              ip6h, MBLKL(mp));
7723 7733  
7724 7734          ASSERT(delta != -1);
7725 7735  
7726 7736          plen += delta;
7727 7737          mp->b_wptr += delta;
7728 7738  
7729 7739          /*
7730 7740           * Paranoia
7731 7741           */
7732 7742          db = mp->b_datap;
7733 7743  
7734 7744          ASSERT3P(mp->b_wptr, <=, db->db_lim);
7735 7745          ASSERT3P(mp->b_rptr, <=, db->db_lim);
7736 7746  
7737 7747          ASSERT3P(mp->b_wptr, >=, db->db_base);
7738 7748          ASSERT3P(mp->b_rptr, >=, db->db_base);
7739 7749          /* End paranoia */
7740 7750  
7741 7751          ip6h->ip6_plen = htons(plen);
7742 7752  
7743 7753          return (mp);
7744 7754  }
7745 7755  
7746 7756  /* Whack the labels and update ip_xmit_attr_t as needed */
7747 7757  mblk_t *
7748 7758  sadb_whack_label(mblk_t *mp, ipsa_t *assoc, ip_xmit_attr_t *ixa,
7749 7759      kstat_named_t *counter, ipdropper_t *dropper)
7750 7760  {
7751 7761          int adjust;
7752 7762          int iplen;
7753 7763  
7754 7764          if (ixa->ixa_flags & IXAF_IS_IPV4) {
7755 7765                  ipha_t          *ipha = (ipha_t *)mp->b_rptr;
7756 7766  
7757 7767                  ASSERT(IPH_HDR_VERSION(ipha) == IPV4_VERSION);
7758 7768                  iplen = ntohs(ipha->ipha_length);
7759 7769                  mp = sadb_whack_label_v4(mp, assoc, counter, dropper);
7760 7770                  if (mp == NULL)
7761 7771                          return (NULL);
7762 7772  
7763 7773                  ipha = (ipha_t *)mp->b_rptr;
7764 7774                  ASSERT(IPH_HDR_VERSION(ipha) == IPV4_VERSION);
7765 7775                  adjust = (int)ntohs(ipha->ipha_length) - iplen;
7766 7776          } else {
7767 7777                  ip6_t           *ip6h = (ip6_t *)mp->b_rptr;
7768 7778  
7769 7779                  ASSERT(IPH_HDR_VERSION(ip6h) == IPV6_VERSION);
7770 7780                  iplen = ntohs(ip6h->ip6_plen);
7771 7781                  mp = sadb_whack_label_v6(mp, assoc, counter, dropper);
7772 7782                  if (mp == NULL)
7773 7783                          return (NULL);
7774 7784  
7775 7785                  ip6h = (ip6_t *)mp->b_rptr;
7776 7786                  ASSERT(IPH_HDR_VERSION(ip6h) == IPV6_VERSION);
7777 7787                  adjust = (int)ntohs(ip6h->ip6_plen) - iplen;
7778 7788          }
7779 7789          ixa->ixa_pktlen += adjust;
7780 7790          ixa->ixa_ip_hdr_length += adjust;
7781 7791          return (mp);
7782 7792  }
7783 7793  
7784 7794  /*
7785 7795   * If this is an outgoing SA then add some fuzz to the
7786 7796   * SOFT EXPIRE time. The reason for this is to stop
7787 7797   * peers trying to renegotiate SOFT expiring SA's at
7788 7798   * the same time. The amount of fuzz needs to be at
7789 7799   * least 8 seconds which is the typical interval
7790 7800   * sadb_ager(), although this is only a guide as it
7791 7801   * selftunes.
7792 7802   */
7793 7803  static void
7794 7804  lifetime_fuzz(ipsa_t *assoc)
7795 7805  {
7796 7806          uint8_t rnd;
7797 7807  
7798 7808          if (assoc->ipsa_softaddlt == 0)
7799 7809                  return;
7800 7810  
7801 7811          (void) random_get_pseudo_bytes(&rnd, sizeof (rnd));
7802 7812          rnd = (rnd & 0xF) + 8;
7803 7813          assoc->ipsa_softexpiretime -= rnd;
7804 7814          assoc->ipsa_softaddlt -= rnd;
7805 7815  }
7806 7816  
7807 7817  static void
7808 7818  destroy_ipsa_pair(ipsap_t *ipsapp)
7809 7819  {
7810 7820          /*
7811 7821           * Because of the multi-line macro nature of IPSA_REFRELE, keep
7812 7822           * them in { }.
7813 7823           */
7814 7824          if (ipsapp->ipsap_sa_ptr != NULL) {
7815 7825                  IPSA_REFRELE(ipsapp->ipsap_sa_ptr);
7816 7826          }
7817 7827          if (ipsapp->ipsap_psa_ptr != NULL) {
7818 7828                  IPSA_REFRELE(ipsapp->ipsap_psa_ptr);
7819 7829          }
7820 7830          init_ipsa_pair(ipsapp);
7821 7831  }
7822 7832  
7823 7833  static void
7824 7834  init_ipsa_pair(ipsap_t *ipsapp)
7825 7835  {
7826 7836          ipsapp->ipsap_bucket = NULL;
7827 7837          ipsapp->ipsap_sa_ptr = NULL;
7828 7838          ipsapp->ipsap_pbucket = NULL;
7829 7839          ipsapp->ipsap_psa_ptr = NULL;
7830 7840  }
7831 7841  
7832 7842  /*
7833 7843   * The sadb_ager() function walks through the hash tables of SA's and ages
7834 7844   * them, if the SA expires as a result, its marked as DEAD and will be reaped
7835 7845   * the next time sadb_ager() runs. SA's which are paired or have a peer (same
7836 7846   * SA appears in both the inbound and outbound tables because its not possible
7837 7847   * to determine its direction) are placed on a list when they expire. This is
7838 7848   * to ensure that pair/peer SA's are reaped at the same time, even if they
7839 7849   * expire at different times.
7840 7850   *
7841 7851   * This function is called twice by sadb_ager(), one after processing the
7842 7852   * inbound table, then again after processing the outbound table.
7843 7853   */
7844 7854  void
7845 7855  age_pair_peer_list(templist_t *haspeerlist, sadb_t *sp, boolean_t outbound)
7846 7856  {
7847 7857          templist_t *listptr;
7848 7858          int outhash;
7849 7859          isaf_t *bucket;
7850 7860          boolean_t haspeer;
7851 7861          ipsa_t *peer_assoc, *dying;
7852 7862          /*
7853 7863           * Haspeer cases will contain both IPv4 and IPv6.  This code
7854 7864           * is address independent.
7855 7865           */
7856 7866          while (haspeerlist != NULL) {
7857 7867                  /* "dying" contains the SA that has a peer. */
7858 7868                  dying = haspeerlist->ipsa;
7859 7869                  haspeer = (dying->ipsa_haspeer);
7860 7870                  listptr = haspeerlist;
7861 7871                  haspeerlist = listptr->next;
7862 7872                  kmem_free(listptr, sizeof (*listptr));
7863 7873                  /*
7864 7874                   * Pick peer bucket based on addrfam.
7865 7875                   */
7866 7876                  if (outbound) {
7867 7877                          if (haspeer)
7868 7878                                  bucket = INBOUND_BUCKET(sp, dying->ipsa_spi);
7869 7879                          else
7870 7880                                  bucket = INBOUND_BUCKET(sp,
7871 7881                                      dying->ipsa_otherspi);
7872 7882                  } else { /* inbound */
7873 7883                          if (haspeer) {
7874 7884                                  if (dying->ipsa_addrfam == AF_INET6) {
7875 7885                                          outhash = OUTBOUND_HASH_V6(sp,
7876 7886                                              *((in6_addr_t *)&dying->
7877 7887                                              ipsa_dstaddr));
7878 7888                                  } else {
7879 7889                                          outhash = OUTBOUND_HASH_V4(sp,
7880 7890                                              *((ipaddr_t *)&dying->
7881 7891                                              ipsa_dstaddr));
7882 7892                                  }
7883 7893                          } else if (dying->ipsa_addrfam == AF_INET6) {
7884 7894                                  outhash = OUTBOUND_HASH_V6(sp,
7885 7895                                      *((in6_addr_t *)&dying->
7886 7896                                      ipsa_srcaddr));
7887 7897                          } else {
7888 7898                                  outhash = OUTBOUND_HASH_V4(sp,
7889 7899                                      *((ipaddr_t *)&dying->
7890 7900                                      ipsa_srcaddr));
7891 7901                          }
7892 7902                          bucket = &(sp->sdb_of[outhash]);
7893 7903                  }
7894 7904  
7895 7905                  mutex_enter(&bucket->isaf_lock);
7896 7906                  /*
7897 7907                   * "haspeer" SA's have the same src/dst address ordering,
7898 7908                   * "paired" SA's have the src/dst addresses reversed.
7899 7909                   */
7900 7910                  if (haspeer) {
7901 7911                          peer_assoc = ipsec_getassocbyspi(bucket,
7902 7912                              dying->ipsa_spi, dying->ipsa_srcaddr,
7903 7913                              dying->ipsa_dstaddr, dying->ipsa_addrfam);
7904 7914                  } else {
7905 7915                          peer_assoc = ipsec_getassocbyspi(bucket,
7906 7916                              dying->ipsa_otherspi, dying->ipsa_dstaddr,
7907 7917                              dying->ipsa_srcaddr, dying->ipsa_addrfam);
7908 7918                  }
7909 7919  
7910 7920                  mutex_exit(&bucket->isaf_lock);
7911 7921                  if (peer_assoc != NULL) {
7912 7922                          mutex_enter(&peer_assoc->ipsa_lock);
7913 7923                          mutex_enter(&dying->ipsa_lock);
7914 7924                          if (!haspeer) {
7915 7925                                  /*
7916 7926                                   * Only SA's which have a "peer" or are
7917 7927                                   * "paired" end up on this list, so this
7918 7928                                   * must be a "paired" SA, update the flags
7919 7929                                   * to break the pair.
7920 7930                                   */
7921 7931                                  peer_assoc->ipsa_otherspi = 0;
7922 7932                                  peer_assoc->ipsa_flags &= ~IPSA_F_PAIRED;
7923 7933                                  dying->ipsa_otherspi = 0;
7924 7934                                  dying->ipsa_flags &= ~IPSA_F_PAIRED;
7925 7935                          }
7926 7936                          if (haspeer || outbound) {
7927 7937                                  /*
7928 7938                                   * Update the state of the "inbound" SA when
7929 7939                                   * the "outbound" SA has expired. Don't update
7930 7940                                   * the "outbound" SA when the "inbound" SA
7931 7941                                   * SA expires because setting the hard_addtime
7932 7942                                   * below will cause this to happen.
7933 7943                                   */
7934 7944                                  peer_assoc->ipsa_state = dying->ipsa_state;
7935 7945                          }
7936 7946                          if (dying->ipsa_state == IPSA_STATE_DEAD)
7937 7947                                  peer_assoc->ipsa_hardexpiretime = 1;
7938 7948  
7939 7949                          mutex_exit(&dying->ipsa_lock);
7940 7950                          mutex_exit(&peer_assoc->ipsa_lock);
7941 7951                          IPSA_REFRELE(peer_assoc);
7942 7952                  }
7943 7953                  IPSA_REFRELE(dying);
7944 7954          }
7945 7955  }
7946 7956  
7947 7957  /*
7948 7958   * Ensure that the IV used for CCM mode never repeats. The IV should
7949 7959   * only be updated by this function. Also check to see if the IV
7950 7960   * is about to wrap and generate a SOFT Expire. This function is only
7951 7961   * called for outgoing packets, the IV for incomming packets is taken
7952 7962   * from the wire. If the outgoing SA needs to be expired, update
7953 7963   * the matching incomming SA.
7954 7964   */
7955 7965  boolean_t
7956 7966  update_iv(uint8_t *iv_ptr, queue_t *pfkey_q, ipsa_t *assoc,
7957 7967      ipsecesp_stack_t *espstack)
7958 7968  {
7959 7969          boolean_t rc = B_TRUE;
7960 7970          isaf_t *inbound_bucket;
7961 7971          sadb_t *sp;
7962 7972          ipsa_t *pair_sa = NULL;
7963 7973          int sa_new_state = 0;
7964 7974  
7965 7975          /* For non counter modes, the IV is random data. */
7966 7976          if (!(assoc->ipsa_flags & IPSA_F_COUNTERMODE)) {
7967 7977                  (void) random_get_pseudo_bytes(iv_ptr, assoc->ipsa_iv_len);
7968 7978                  return (rc);
7969 7979          }
7970 7980  
7971 7981          mutex_enter(&assoc->ipsa_lock);
7972 7982  
7973 7983          (*assoc->ipsa_iv)++;
7974 7984  
7975 7985          if (*assoc->ipsa_iv == assoc->ipsa_iv_hardexpire) {
7976 7986                  sa_new_state = IPSA_STATE_DEAD;
7977 7987                  rc = B_FALSE;
7978 7988          } else if (*assoc->ipsa_iv == assoc->ipsa_iv_softexpire) {
7979 7989                  if (assoc->ipsa_state != IPSA_STATE_DYING) {
7980 7990                          /*
7981 7991                           * This SA may have already been expired when its
7982 7992                           * PAIR_SA expired.
7983 7993                           */
7984 7994                          sa_new_state = IPSA_STATE_DYING;
7985 7995                  }
7986 7996          }
7987 7997          if (sa_new_state) {
7988 7998                  /*
7989 7999                   * If there is a state change, we need to update this SA
7990 8000                   * and its "pair", we can find the bucket for the "pair" SA
7991 8001                   * while holding the ipsa_t mutex, but we won't actually
7992 8002                   * update anything untill the ipsa_t mutex has been released
7993 8003                   * for _this_ SA.
7994 8004                   */
7995 8005                  assoc->ipsa_state = sa_new_state;
7996 8006                  if (assoc->ipsa_addrfam == AF_INET6) {
7997 8007                          sp = &espstack->esp_sadb.s_v6;
7998 8008                  } else {
7999 8009                          sp = &espstack->esp_sadb.s_v4;
8000 8010                  }
8001 8011                  inbound_bucket = INBOUND_BUCKET(sp, assoc->ipsa_otherspi);
8002 8012                  sadb_expire_assoc(pfkey_q, assoc);
8003 8013          }
8004 8014          if (rc == B_TRUE)
8005 8015                  bcopy(assoc->ipsa_iv, iv_ptr, assoc->ipsa_iv_len);
8006 8016  
8007 8017          mutex_exit(&assoc->ipsa_lock);
8008 8018  
8009 8019          if (sa_new_state) {
8010 8020                  /* Find the inbound SA, need to lock hash bucket. */
8011 8021                  mutex_enter(&inbound_bucket->isaf_lock);
8012 8022                  pair_sa = ipsec_getassocbyspi(inbound_bucket,
8013 8023                      assoc->ipsa_otherspi, assoc->ipsa_dstaddr,
8014 8024                      assoc->ipsa_srcaddr, assoc->ipsa_addrfam);
8015 8025                  mutex_exit(&inbound_bucket->isaf_lock);
8016 8026                  if (pair_sa != NULL) {
8017 8027                          mutex_enter(&pair_sa->ipsa_lock);
8018 8028                          pair_sa->ipsa_state = sa_new_state;
8019 8029                          mutex_exit(&pair_sa->ipsa_lock);
8020 8030                          IPSA_REFRELE(pair_sa);
8021 8031                  }
8022 8032          }
8023 8033  
8024 8034          return (rc);
8025 8035  }
8026 8036  
8027 8037  void
8028 8038  ccm_params_init(ipsa_t *assoc, uchar_t *esph, uint_t data_len, uchar_t *iv_ptr,
8029 8039      ipsa_cm_mech_t *cm_mech, crypto_data_t *crypto_data)
8030 8040  {
8031 8041          uchar_t *nonce;
8032 8042          crypto_mechanism_t *combined_mech;
8033 8043          CK_AES_CCM_PARAMS *params;
8034 8044  
8035 8045          combined_mech = (crypto_mechanism_t *)cm_mech;
8036 8046          params = (CK_AES_CCM_PARAMS *)(combined_mech + 1);
8037 8047          nonce = (uchar_t *)(params + 1);
8038 8048          params->ulMACSize = assoc->ipsa_mac_len;
8039 8049          params->ulNonceSize = assoc->ipsa_nonce_len;
8040 8050          params->ulAuthDataSize = sizeof (esph_t);
8041 8051          params->ulDataSize = data_len;
8042 8052          params->nonce = nonce;
8043 8053          params->authData = esph;
8044 8054  
8045 8055          cm_mech->combined_mech.cm_type = assoc->ipsa_emech.cm_type;
8046 8056          cm_mech->combined_mech.cm_param_len = sizeof (CK_AES_CCM_PARAMS);
8047 8057          cm_mech->combined_mech.cm_param = (caddr_t)params;
8048 8058          /* See gcm_params_init() for comments. */
8049 8059          bcopy(assoc->ipsa_nonce, nonce, assoc->ipsa_saltlen);
8050 8060          nonce += assoc->ipsa_saltlen;
8051 8061          bcopy(iv_ptr, nonce, assoc->ipsa_iv_len);
8052 8062          crypto_data->cd_miscdata = NULL;
8053 8063  }
8054 8064  
8055 8065  /* ARGSUSED */
8056 8066  void
8057 8067  cbc_params_init(ipsa_t *assoc, uchar_t *esph, uint_t data_len, uchar_t *iv_ptr,
8058 8068      ipsa_cm_mech_t *cm_mech, crypto_data_t *crypto_data)
8059 8069  {
8060 8070          cm_mech->combined_mech.cm_type = assoc->ipsa_emech.cm_type;
8061 8071          cm_mech->combined_mech.cm_param_len = 0;
8062 8072          cm_mech->combined_mech.cm_param = NULL;
8063 8073          crypto_data->cd_miscdata = (char *)iv_ptr;
8064 8074  }
8065 8075  
8066 8076  /* ARGSUSED */
8067 8077  void
8068 8078  gcm_params_init(ipsa_t *assoc, uchar_t *esph, uint_t data_len, uchar_t *iv_ptr,
8069 8079      ipsa_cm_mech_t *cm_mech, crypto_data_t *crypto_data)
8070 8080  {
8071 8081          uchar_t *nonce;
8072 8082          crypto_mechanism_t *combined_mech;
8073 8083          CK_AES_GCM_PARAMS *params;
8074 8084  
8075 8085          combined_mech = (crypto_mechanism_t *)cm_mech;
8076 8086          params = (CK_AES_GCM_PARAMS *)(combined_mech + 1);
8077 8087          nonce = (uchar_t *)(params + 1);
8078 8088  
8079 8089          params->pIv = nonce;
8080 8090          params->ulIvLen = assoc->ipsa_nonce_len;
8081 8091          params->ulIvBits = SADB_8TO1(assoc->ipsa_nonce_len);
8082 8092          params->pAAD = esph;
8083 8093          params->ulAADLen = sizeof (esph_t);
8084 8094          params->ulTagBits = SADB_8TO1(assoc->ipsa_mac_len);
8085 8095  
8086 8096          cm_mech->combined_mech.cm_type = assoc->ipsa_emech.cm_type;
8087 8097          cm_mech->combined_mech.cm_param_len = sizeof (CK_AES_GCM_PARAMS);
8088 8098          cm_mech->combined_mech.cm_param = (caddr_t)params;
8089 8099          /*
8090 8100           * Create the nonce, which is made up of the salt and the IV.
8091 8101           * Copy the salt from the SA and the IV from the packet.
8092 8102           * For inbound packets we copy the IV from the packet because it
8093 8103           * was set by the sending system, for outbound packets we copy the IV
8094 8104           * from the packet because the IV in the SA may be changed by another
8095 8105           * thread, the IV in the packet was created while holding a mutex.
8096 8106           */
8097 8107          bcopy(assoc->ipsa_nonce, nonce, assoc->ipsa_saltlen);
8098 8108          nonce += assoc->ipsa_saltlen;
8099 8109          bcopy(iv_ptr, nonce, assoc->ipsa_iv_len);
8100 8110          crypto_data->cd_miscdata = NULL;
8101 8111  }
  
    | 
      ↓ open down ↓ | 
    4951 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX