Print this page
8381 Convert ipsec_alg_lock from mutex to rwlock


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.

  24  */
  25 
  26 #include <sys/types.h>
  27 #include <sys/stream.h>
  28 #include <sys/stropts.h>
  29 #include <sys/strsubr.h>
  30 #include <sys/errno.h>
  31 #include <sys/ddi.h>
  32 #include <sys/debug.h>
  33 #include <sys/cmn_err.h>
  34 #include <sys/stream.h>
  35 #include <sys/strlog.h>
  36 #include <sys/kmem.h>
  37 #include <sys/sunddi.h>
  38 #include <sys/tihdr.h>
  39 #include <sys/atomic.h>
  40 #include <sys/socket.h>
  41 #include <sys/sysmacros.h>
  42 #include <sys/crypto/common.h>
  43 #include <sys/crypto/api.h>


3181                 if ((akey->sadb_key_bits & 0x7) != 0)
3182                         newbie->ipsa_authkeylen++;
3183                 newbie->ipsa_authkey = kmem_alloc(newbie->ipsa_authkeylen,
3184                     KM_NOSLEEP);
3185                 if (newbie->ipsa_authkey == NULL) {
3186                         error = ENOMEM;
3187                         mutex_exit(&newbie->ipsa_lock);
3188                         goto error;
3189                 }
3190                 bcopy(akey + 1, newbie->ipsa_authkey, newbie->ipsa_authkeylen);
3191                 bzero(akey + 1, newbie->ipsa_authkeylen);
3192 
3193                 /*
3194                  * Pre-initialize the kernel crypto framework key
3195                  * structure.
3196                  */
3197                 newbie->ipsa_kcfauthkey.ck_format = CRYPTO_KEY_RAW;
3198                 newbie->ipsa_kcfauthkey.ck_length = newbie->ipsa_authkeybits;
3199                 newbie->ipsa_kcfauthkey.ck_data = newbie->ipsa_authkey;
3200 
3201                 mutex_enter(&ipss->ipsec_alg_lock);
3202                 alg = ipss->ipsec_alglists[IPSEC_ALG_AUTH]
3203                     [newbie->ipsa_auth_alg];
3204                 if (alg != NULL && ALG_VALID(alg)) {
3205                         newbie->ipsa_amech.cm_type = alg->alg_mech_type;
3206                         newbie->ipsa_amech.cm_param =
3207                             (char *)&newbie->ipsa_mac_len;
3208                         newbie->ipsa_amech.cm_param_len = sizeof (size_t);
3209                         newbie->ipsa_mac_len = (size_t)alg->alg_datalen;
3210                 } else {
3211                         newbie->ipsa_amech.cm_type = CRYPTO_MECHANISM_INVALID;
3212                 }
3213                 error = ipsec_create_ctx_tmpl(newbie, IPSEC_ALG_AUTH);
3214                 mutex_exit(&ipss->ipsec_alg_lock);
3215                 if (error != 0) {
3216                         mutex_exit(&newbie->ipsa_lock);
3217                         /*
3218                          * An error here indicates that alg is the wrong type
3219                          * (IE: not authentication) or its not in the alg tables
3220                          * created by ipsecalgs(1m), or Kcf does not like the
3221                          * parameters passed in with this algorithm, which is
3222                          * probably a coding error!
3223                          */
3224                         *diagnostic = SADB_X_DIAGNOSTIC_BAD_CTX;
3225 
3226                         goto error;
3227                 }
3228         }
3229 
3230         if (ekey != NULL) {
3231                 mutex_enter(&ipss->ipsec_alg_lock);
3232                 async = async || (ipss->ipsec_algs_exec_mode[IPSEC_ALG_ENCR] ==
3233                     IPSEC_ALGS_EXEC_ASYNC);
3234                 alg = ipss->ipsec_alglists[IPSEC_ALG_ENCR]
3235                     [newbie->ipsa_encr_alg];
3236 
3237                 if (alg != NULL && ALG_VALID(alg)) {
3238                         newbie->ipsa_emech.cm_type = alg->alg_mech_type;
3239                         newbie->ipsa_datalen = alg->alg_datalen;
3240                         if (alg->alg_flags & ALG_FLAG_COUNTERMODE)
3241                                 newbie->ipsa_flags |= IPSA_F_COUNTERMODE;
3242 
3243                         if (alg->alg_flags & ALG_FLAG_COMBINED) {
3244                                 newbie->ipsa_flags |= IPSA_F_COMBINED;
3245                                 newbie->ipsa_mac_len =  alg->alg_icvlen;
3246                         }
3247 
3248                         if (alg->alg_flags & ALG_FLAG_CCM)
3249                                 newbie->ipsa_noncefunc = ccm_params_init;
3250                         else if (alg->alg_flags & ALG_FLAG_GCM)
3251                                 newbie->ipsa_noncefunc = gcm_params_init;
3252                         else newbie->ipsa_noncefunc = cbc_params_init;
3253 
3254                         newbie->ipsa_saltlen = alg->alg_saltlen;
3255                         newbie->ipsa_saltbits = SADB_8TO1(newbie->ipsa_saltlen);
3256                         newbie->ipsa_iv_len = alg->alg_ivlen;
3257                         newbie->ipsa_nonce_len = newbie->ipsa_saltlen +
3258                             newbie->ipsa_iv_len;
3259                         newbie->ipsa_emech.cm_param = NULL;
3260                         newbie->ipsa_emech.cm_param_len = 0;
3261                 } else {
3262                         newbie->ipsa_emech.cm_type = CRYPTO_MECHANISM_INVALID;
3263                 }
3264                 mutex_exit(&ipss->ipsec_alg_lock);
3265 
3266                 /*
3267                  * The byte stream following the sadb_key_t is made up of:
3268                  * key bytes, [salt bytes], [IV initial value]
3269                  * All of these have variable length. The IV is typically
3270                  * randomly generated by this function and not passed in.
3271                  * By supporting the injection of a known IV, the whole
3272                  * IPsec subsystem and the underlying crypto subsystem
3273                  * can be tested with known test vectors.
3274                  *
3275                  * The keying material has been checked by ext_check()
3276                  * and ipsec_valid_key_size(), after removing salt/IV
3277                  * bits, whats left is the encryption key. If this is too
3278                  * short, ipsec_create_ctx_tmpl() will fail and the SA
3279                  * won't get created.
3280                  *
3281                  * set ipsa_encrkeylen to length of key only.
3282                  */
3283                 newbie->ipsa_encrkeybits = ekey->sadb_key_bits;
3284                 newbie->ipsa_encrkeybits -= ekey->sadb_key_reserved;


3356                                 } else {
3357                                         (void) random_get_pseudo_bytes(
3358                                             (uint8_t *)newbie->ipsa_iv,
3359                                             newbie->ipsa_iv_len);
3360                                 }
3361                                 newbie->ipsa_iv_softexpire =
3362                                     (*newbie->ipsa_iv) << 9;
3363                                 newbie->ipsa_iv_hardexpire = *newbie->ipsa_iv;
3364                         }
3365                 }
3366                 bzero((ekey + 1), SADB_1TO8(ekey->sadb_key_bits));
3367 
3368                 /*
3369                  * Pre-initialize the kernel crypto framework key
3370                  * structure.
3371                  */
3372                 newbie->ipsa_kcfencrkey.ck_format = CRYPTO_KEY_RAW;
3373                 newbie->ipsa_kcfencrkey.ck_length = newbie->ipsa_encrkeybits;
3374                 newbie->ipsa_kcfencrkey.ck_data = newbie->ipsa_encrkey;
3375 
3376                 mutex_enter(&ipss->ipsec_alg_lock);
3377                 error = ipsec_create_ctx_tmpl(newbie, IPSEC_ALG_ENCR);
3378                 mutex_exit(&ipss->ipsec_alg_lock);
3379                 if (error != 0) {
3380                         mutex_exit(&newbie->ipsa_lock);
3381                         /* See above for error explanation. */
3382                         *diagnostic = SADB_X_DIAGNOSTIC_BAD_CTX;
3383                         goto error;
3384                 }
3385         }
3386 
3387         if (async)
3388                 newbie->ipsa_flags |= IPSA_F_ASYNC;
3389 
3390         /*
3391          * Ptrs to processing functions.
3392          */
3393         if (newbie->ipsa_type == SADB_SATYPE_ESP)
3394                 ipsecesp_init_funcs(newbie);
3395         else
3396                 ipsecah_init_funcs(newbie);
3397         ASSERT(newbie->ipsa_output_func != NULL &&
3398             newbie->ipsa_input_func != NULL);


5264 static uint8_t *
5265 sadb_new_algdesc(uint8_t *start, uint8_t *limit,
5266     sadb_x_ecomb_t *ecomb, uint8_t satype, uint8_t algtype,
5267     uint8_t alg, uint16_t minbits, uint16_t maxbits, ipsec_stack_t *ipss)
5268 {
5269         uint8_t *cur = start;
5270         ipsec_alginfo_t *algp;
5271         sadb_x_algdesc_t *algdesc = (sadb_x_algdesc_t *)cur;
5272 
5273         cur += sizeof (*algdesc);
5274         if (cur >= limit)
5275                 return (NULL);
5276 
5277         ecomb->sadb_x_ecomb_numalgs++;
5278 
5279         /*
5280          * Normalize vs. crypto framework's limits.  This way, you can specify
5281          * a stronger policy, and when the framework loads a stronger version,
5282          * you can just keep plowing w/o rewhacking your SPD.
5283          */
5284         mutex_enter(&ipss->ipsec_alg_lock);
5285         algp = ipss->ipsec_alglists[(algtype == SADB_X_ALGTYPE_AUTH) ?
5286             IPSEC_ALG_AUTH : IPSEC_ALG_ENCR][alg];
5287         if (algp == NULL) {
5288                 mutex_exit(&ipss->ipsec_alg_lock);
5289                 return (NULL);  /* Algorithm doesn't exist.  Fail gracefully. */
5290         }
5291         if (minbits < algp->alg_ef_minbits)
5292                 minbits = algp->alg_ef_minbits;
5293         if (maxbits > algp->alg_ef_maxbits)
5294                 maxbits = algp->alg_ef_maxbits;
5295         mutex_exit(&ipss->ipsec_alg_lock);
5296 
5297         algdesc->sadb_x_algdesc_reserved = SADB_8TO1(algp->alg_saltlen);
5298         algdesc->sadb_x_algdesc_satype = satype;
5299         algdesc->sadb_x_algdesc_algtype = algtype;
5300         algdesc->sadb_x_algdesc_alg = alg;
5301         algdesc->sadb_x_algdesc_minbits = minbits;
5302         algdesc->sadb_x_algdesc_maxbits = maxbits;
5303 
5304         return (cur);
5305 }
5306 
5307 /*
5308  * Convert the given ipsec_action_t into an ecomb starting at *ecomb
5309  * which must fit before *limit
5310  *
5311  * return NULL if we ran out of room or a pointer to the end of the ecomb.
5312  */
5313 static uint8_t *
5314 sadb_action_to_ecomb(uint8_t *start, uint8_t *limit, ipsec_action_t *act,
5315     netstack_t *ns)


5757         uint16_t sport_typecode;
5758         uint16_t dport_typecode;
5759         uint8_t check_proto;
5760         boolean_t tunnel_mode = (acqrec->ipsacq_inneraddrfam != 0);
5761 
5762         ASSERT(MUTEX_HELD(&acqrec->ipsacq_lock));
5763 
5764         pfkeymp = sadb_keysock_out(0);
5765         if (pfkeymp == NULL)
5766                 return (NULL);
5767 
5768         /*
5769          * First, allocate a basic ACQUIRE message
5770          */
5771         allocsize = sizeof (sadb_msg_t) + sizeof (sadb_address_t) +
5772             sizeof (sadb_address_t) + sizeof (sadb_prop_t);
5773 
5774         /* Make sure there's enough to cover both AF_INET and AF_INET6. */
5775         allocsize += 2 * sizeof (struct sockaddr_in6);
5776 
5777         mutex_enter(&ipss->ipsec_alg_lock);
5778         /* NOTE:  The lock is now held through to this function's return. */
5779         allocsize += ipss->ipsec_nalgs[IPSEC_ALG_AUTH] *
5780             ipss->ipsec_nalgs[IPSEC_ALG_ENCR] * sizeof (sadb_comb_t);
5781 
5782         if (tunnel_mode) {
5783                 /* Tunnel mode! */
5784                 allocsize += 2 * sizeof (sadb_address_t);
5785                 /* Enough to cover both AF_INET and AF_INET6. */
5786                 allocsize += 2 * sizeof (struct sockaddr_in6);
5787         }
5788 
5789         msgmp = allocb(allocsize, BPRI_HI);
5790         if (msgmp == NULL) {
5791                 freeb(pfkeymp);
5792                 mutex_exit(&ipss->ipsec_alg_lock);
5793                 return (NULL);
5794         }
5795 
5796         pfkeymp->b_cont = msgmp;
5797         cur = msgmp->b_rptr;
5798         end = cur + allocsize;
5799         samsg = (sadb_msg_t *)cur;
5800         cur += sizeof (sadb_msg_t);
5801 
5802         af = acqrec->ipsacq_addrfam;
5803         switch (af) {
5804         case AF_INET:
5805                 check_proto = IPPROTO_ICMP;
5806                 break;
5807         case AF_INET6:
5808                 check_proto = IPPROTO_ICMPV6;
5809                 break;
5810         default:
5811                 /* This should never happen unless we have kernel bugs. */
5812                 cmn_err(CE_WARN,
5813                     "sadb_setup_acquire:  corrupt ACQUIRE record.\n");
5814                 ASSERT(0);
5815                 mutex_exit(&ipss->ipsec_alg_lock);
5816                 return (NULL);
5817         }
5818 
5819         samsg->sadb_msg_version = PF_KEY_V2;
5820         samsg->sadb_msg_type = SADB_ACQUIRE;
5821         samsg->sadb_msg_satype = satype;
5822         samsg->sadb_msg_errno = 0;
5823         samsg->sadb_msg_pid = 0;
5824         samsg->sadb_msg_reserved = 0;
5825         samsg->sadb_msg_seq = acqrec->ipsacq_seq;
5826 
5827         ASSERT(MUTEX_HELD(&acqrec->ipsacq_lock));
5828 
5829         if ((acqrec->ipsacq_proto == check_proto) || tunnel_mode) {
5830                 sport_typecode = dport_typecode = 0;
5831         } else {
5832                 sport_typecode = acqrec->ipsacq_srcport;
5833                 dport_typecode = acqrec->ipsacq_dstport;
5834         }
5835 


5842         if (tunnel_mode) {
5843                 sport_typecode = acqrec->ipsacq_srcport;
5844                 dport_typecode = acqrec->ipsacq_dstport;
5845                 cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_SRC,
5846                     acqrec->ipsacq_inneraddrfam, acqrec->ipsacq_innersrc,
5847                     sport_typecode, acqrec->ipsacq_inner_proto,
5848                     acqrec->ipsacq_innersrcpfx);
5849                 cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_DST,
5850                     acqrec->ipsacq_inneraddrfam, acqrec->ipsacq_innerdst,
5851                     dport_typecode, acqrec->ipsacq_inner_proto,
5852                     acqrec->ipsacq_innerdstpfx);
5853         }
5854 
5855         /* XXX Insert identity information here. */
5856 
5857         /* XXXMLS Insert sensitivity information here. */
5858 
5859         if (cur != NULL)
5860                 samsg->sadb_msg_len = SADB_8TO64(cur - msgmp->b_rptr);
5861         else
5862                 mutex_exit(&ipss->ipsec_alg_lock);
5863 
5864         return (pfkeymp);
5865 }
5866 
5867 /*
5868  * Given an SADB_GETSPI message, find an appropriately ranged SA and
5869  * allocate an SA.  If there are message improprieties, return (ipsa_t *)-1.
5870  * If there was a memory allocation error, return NULL.  (Assume NULL !=
5871  * (ipsa_t *)-1).
5872  *
5873  * master_spi is passed in host order.
5874  */
5875 ipsa_t *
5876 sadb_getspi(keysock_in_t *ksi, uint32_t master_spi, int *diagnostic,
5877     netstack_t *ns, uint_t sa_type)
5878 {
5879         sadb_address_t *src =
5880             (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_SRC],
5881             *dst = (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_DST];
5882         sadb_spirange_t *range =


7173         SADB_ALG_UPDATE_WALK(espstack->esp_sadb.s_v4, sdb_if);
7174         SADB_ALG_UPDATE_WALK(espstack->esp_sadb.s_v6, sdb_of);
7175         SADB_ALG_UPDATE_WALK(espstack->esp_sadb.s_v6, sdb_if);
7176 }
7177 
7178 /*
7179  * Creates a context template for the specified SA. This function
7180  * is called when an SA is created and when a context template needs
7181  * to be created due to a change of software provider.
7182  */
7183 int
7184 ipsec_create_ctx_tmpl(ipsa_t *sa, ipsec_algtype_t alg_type)
7185 {
7186         ipsec_alginfo_t *alg;
7187         crypto_mechanism_t mech;
7188         crypto_key_t *key;
7189         crypto_ctx_template_t *sa_tmpl;
7190         int rv;
7191         ipsec_stack_t   *ipss = sa->ipsa_netstack->netstack_ipsec;
7192 
7193         ASSERT(MUTEX_HELD(&ipss->ipsec_alg_lock));
7194         ASSERT(MUTEX_HELD(&sa->ipsa_lock));
7195 
7196         /* get pointers to the algorithm info, context template, and key */
7197         switch (alg_type) {
7198         case IPSEC_ALG_AUTH:
7199                 key = &sa->ipsa_kcfauthkey;
7200                 sa_tmpl = &sa->ipsa_authtmpl;
7201                 alg = ipss->ipsec_alglists[alg_type][sa->ipsa_auth_alg];
7202                 break;
7203         case IPSEC_ALG_ENCR:
7204                 key = &sa->ipsa_kcfencrkey;
7205                 sa_tmpl = &sa->ipsa_encrtmpl;
7206                 alg = ipss->ipsec_alglists[alg_type][sa->ipsa_encr_alg];
7207                 break;
7208         default:
7209                 alg = NULL;
7210         }
7211 
7212         if (alg == NULL || !ALG_VALID(alg))
7213                 return (EINVAL);




   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  * Copyright (c) 2012 Nexenta Systems, Inc. All rights reserved.
  25  */
  26 
  27 #include <sys/types.h>
  28 #include <sys/stream.h>
  29 #include <sys/stropts.h>
  30 #include <sys/strsubr.h>
  31 #include <sys/errno.h>
  32 #include <sys/ddi.h>
  33 #include <sys/debug.h>
  34 #include <sys/cmn_err.h>
  35 #include <sys/stream.h>
  36 #include <sys/strlog.h>
  37 #include <sys/kmem.h>
  38 #include <sys/sunddi.h>
  39 #include <sys/tihdr.h>
  40 #include <sys/atomic.h>
  41 #include <sys/socket.h>
  42 #include <sys/sysmacros.h>
  43 #include <sys/crypto/common.h>
  44 #include <sys/crypto/api.h>


3182                 if ((akey->sadb_key_bits & 0x7) != 0)
3183                         newbie->ipsa_authkeylen++;
3184                 newbie->ipsa_authkey = kmem_alloc(newbie->ipsa_authkeylen,
3185                     KM_NOSLEEP);
3186                 if (newbie->ipsa_authkey == NULL) {
3187                         error = ENOMEM;
3188                         mutex_exit(&newbie->ipsa_lock);
3189                         goto error;
3190                 }
3191                 bcopy(akey + 1, newbie->ipsa_authkey, newbie->ipsa_authkeylen);
3192                 bzero(akey + 1, newbie->ipsa_authkeylen);
3193 
3194                 /*
3195                  * Pre-initialize the kernel crypto framework key
3196                  * structure.
3197                  */
3198                 newbie->ipsa_kcfauthkey.ck_format = CRYPTO_KEY_RAW;
3199                 newbie->ipsa_kcfauthkey.ck_length = newbie->ipsa_authkeybits;
3200                 newbie->ipsa_kcfauthkey.ck_data = newbie->ipsa_authkey;
3201 
3202                 rw_enter(&ipss->ipsec_alg_lock, RW_READER);
3203                 alg = ipss->ipsec_alglists[IPSEC_ALG_AUTH]
3204                     [newbie->ipsa_auth_alg];
3205                 if (alg != NULL && ALG_VALID(alg)) {
3206                         newbie->ipsa_amech.cm_type = alg->alg_mech_type;
3207                         newbie->ipsa_amech.cm_param =
3208                             (char *)&newbie->ipsa_mac_len;
3209                         newbie->ipsa_amech.cm_param_len = sizeof (size_t);
3210                         newbie->ipsa_mac_len = (size_t)alg->alg_datalen;
3211                 } else {
3212                         newbie->ipsa_amech.cm_type = CRYPTO_MECHANISM_INVALID;
3213                 }
3214                 error = ipsec_create_ctx_tmpl(newbie, IPSEC_ALG_AUTH);
3215                 rw_exit(&ipss->ipsec_alg_lock);
3216                 if (error != 0) {
3217                         mutex_exit(&newbie->ipsa_lock);
3218                         /*
3219                          * An error here indicates that alg is the wrong type
3220                          * (IE: not authentication) or its not in the alg tables
3221                          * created by ipsecalgs(1m), or Kcf does not like the
3222                          * parameters passed in with this algorithm, which is
3223                          * probably a coding error!
3224                          */
3225                         *diagnostic = SADB_X_DIAGNOSTIC_BAD_CTX;
3226 
3227                         goto error;
3228                 }
3229         }
3230 
3231         if (ekey != NULL) {
3232                 rw_enter(&ipss->ipsec_alg_lock, RW_READER);
3233                 async = async || (ipss->ipsec_algs_exec_mode[IPSEC_ALG_ENCR] ==
3234                     IPSEC_ALGS_EXEC_ASYNC);
3235                 alg = ipss->ipsec_alglists[IPSEC_ALG_ENCR]
3236                     [newbie->ipsa_encr_alg];
3237 
3238                 if (alg != NULL && ALG_VALID(alg)) {
3239                         newbie->ipsa_emech.cm_type = alg->alg_mech_type;
3240                         newbie->ipsa_datalen = alg->alg_datalen;
3241                         if (alg->alg_flags & ALG_FLAG_COUNTERMODE)
3242                                 newbie->ipsa_flags |= IPSA_F_COUNTERMODE;
3243 
3244                         if (alg->alg_flags & ALG_FLAG_COMBINED) {
3245                                 newbie->ipsa_flags |= IPSA_F_COMBINED;
3246                                 newbie->ipsa_mac_len =  alg->alg_icvlen;
3247                         }
3248 
3249                         if (alg->alg_flags & ALG_FLAG_CCM)
3250                                 newbie->ipsa_noncefunc = ccm_params_init;
3251                         else if (alg->alg_flags & ALG_FLAG_GCM)
3252                                 newbie->ipsa_noncefunc = gcm_params_init;
3253                         else newbie->ipsa_noncefunc = cbc_params_init;
3254 
3255                         newbie->ipsa_saltlen = alg->alg_saltlen;
3256                         newbie->ipsa_saltbits = SADB_8TO1(newbie->ipsa_saltlen);
3257                         newbie->ipsa_iv_len = alg->alg_ivlen;
3258                         newbie->ipsa_nonce_len = newbie->ipsa_saltlen +
3259                             newbie->ipsa_iv_len;
3260                         newbie->ipsa_emech.cm_param = NULL;
3261                         newbie->ipsa_emech.cm_param_len = 0;
3262                 } else {
3263                         newbie->ipsa_emech.cm_type = CRYPTO_MECHANISM_INVALID;
3264                 }
3265                 rw_exit(&ipss->ipsec_alg_lock);
3266 
3267                 /*
3268                  * The byte stream following the sadb_key_t is made up of:
3269                  * key bytes, [salt bytes], [IV initial value]
3270                  * All of these have variable length. The IV is typically
3271                  * randomly generated by this function and not passed in.
3272                  * By supporting the injection of a known IV, the whole
3273                  * IPsec subsystem and the underlying crypto subsystem
3274                  * can be tested with known test vectors.
3275                  *
3276                  * The keying material has been checked by ext_check()
3277                  * and ipsec_valid_key_size(), after removing salt/IV
3278                  * bits, whats left is the encryption key. If this is too
3279                  * short, ipsec_create_ctx_tmpl() will fail and the SA
3280                  * won't get created.
3281                  *
3282                  * set ipsa_encrkeylen to length of key only.
3283                  */
3284                 newbie->ipsa_encrkeybits = ekey->sadb_key_bits;
3285                 newbie->ipsa_encrkeybits -= ekey->sadb_key_reserved;


3357                                 } else {
3358                                         (void) random_get_pseudo_bytes(
3359                                             (uint8_t *)newbie->ipsa_iv,
3360                                             newbie->ipsa_iv_len);
3361                                 }
3362                                 newbie->ipsa_iv_softexpire =
3363                                     (*newbie->ipsa_iv) << 9;
3364                                 newbie->ipsa_iv_hardexpire = *newbie->ipsa_iv;
3365                         }
3366                 }
3367                 bzero((ekey + 1), SADB_1TO8(ekey->sadb_key_bits));
3368 
3369                 /*
3370                  * Pre-initialize the kernel crypto framework key
3371                  * structure.
3372                  */
3373                 newbie->ipsa_kcfencrkey.ck_format = CRYPTO_KEY_RAW;
3374                 newbie->ipsa_kcfencrkey.ck_length = newbie->ipsa_encrkeybits;
3375                 newbie->ipsa_kcfencrkey.ck_data = newbie->ipsa_encrkey;
3376 
3377                 rw_enter(&ipss->ipsec_alg_lock, RW_READER);
3378                 error = ipsec_create_ctx_tmpl(newbie, IPSEC_ALG_ENCR);
3379                 rw_exit(&ipss->ipsec_alg_lock);
3380                 if (error != 0) {
3381                         mutex_exit(&newbie->ipsa_lock);
3382                         /* See above for error explanation. */
3383                         *diagnostic = SADB_X_DIAGNOSTIC_BAD_CTX;
3384                         goto error;
3385                 }
3386         }
3387 
3388         if (async)
3389                 newbie->ipsa_flags |= IPSA_F_ASYNC;
3390 
3391         /*
3392          * Ptrs to processing functions.
3393          */
3394         if (newbie->ipsa_type == SADB_SATYPE_ESP)
3395                 ipsecesp_init_funcs(newbie);
3396         else
3397                 ipsecah_init_funcs(newbie);
3398         ASSERT(newbie->ipsa_output_func != NULL &&
3399             newbie->ipsa_input_func != NULL);


5265 static uint8_t *
5266 sadb_new_algdesc(uint8_t *start, uint8_t *limit,
5267     sadb_x_ecomb_t *ecomb, uint8_t satype, uint8_t algtype,
5268     uint8_t alg, uint16_t minbits, uint16_t maxbits, ipsec_stack_t *ipss)
5269 {
5270         uint8_t *cur = start;
5271         ipsec_alginfo_t *algp;
5272         sadb_x_algdesc_t *algdesc = (sadb_x_algdesc_t *)cur;
5273 
5274         cur += sizeof (*algdesc);
5275         if (cur >= limit)
5276                 return (NULL);
5277 
5278         ecomb->sadb_x_ecomb_numalgs++;
5279 
5280         /*
5281          * Normalize vs. crypto framework's limits.  This way, you can specify
5282          * a stronger policy, and when the framework loads a stronger version,
5283          * you can just keep plowing w/o rewhacking your SPD.
5284          */
5285         rw_enter(&ipss->ipsec_alg_lock, RW_READER);
5286         algp = ipss->ipsec_alglists[(algtype == SADB_X_ALGTYPE_AUTH) ?
5287             IPSEC_ALG_AUTH : IPSEC_ALG_ENCR][alg];
5288         if (algp == NULL) {
5289                 rw_exit(&ipss->ipsec_alg_lock);
5290                 return (NULL);  /* Algorithm doesn't exist.  Fail gracefully. */
5291         }
5292         if (minbits < algp->alg_ef_minbits)
5293                 minbits = algp->alg_ef_minbits;
5294         if (maxbits > algp->alg_ef_maxbits)
5295                 maxbits = algp->alg_ef_maxbits;
5296         rw_exit(&ipss->ipsec_alg_lock);
5297 
5298         algdesc->sadb_x_algdesc_reserved = SADB_8TO1(algp->alg_saltlen);
5299         algdesc->sadb_x_algdesc_satype = satype;
5300         algdesc->sadb_x_algdesc_algtype = algtype;
5301         algdesc->sadb_x_algdesc_alg = alg;
5302         algdesc->sadb_x_algdesc_minbits = minbits;
5303         algdesc->sadb_x_algdesc_maxbits = maxbits;
5304 
5305         return (cur);
5306 }
5307 
5308 /*
5309  * Convert the given ipsec_action_t into an ecomb starting at *ecomb
5310  * which must fit before *limit
5311  *
5312  * return NULL if we ran out of room or a pointer to the end of the ecomb.
5313  */
5314 static uint8_t *
5315 sadb_action_to_ecomb(uint8_t *start, uint8_t *limit, ipsec_action_t *act,
5316     netstack_t *ns)


5758         uint16_t sport_typecode;
5759         uint16_t dport_typecode;
5760         uint8_t check_proto;
5761         boolean_t tunnel_mode = (acqrec->ipsacq_inneraddrfam != 0);
5762 
5763         ASSERT(MUTEX_HELD(&acqrec->ipsacq_lock));
5764 
5765         pfkeymp = sadb_keysock_out(0);
5766         if (pfkeymp == NULL)
5767                 return (NULL);
5768 
5769         /*
5770          * First, allocate a basic ACQUIRE message
5771          */
5772         allocsize = sizeof (sadb_msg_t) + sizeof (sadb_address_t) +
5773             sizeof (sadb_address_t) + sizeof (sadb_prop_t);
5774 
5775         /* Make sure there's enough to cover both AF_INET and AF_INET6. */
5776         allocsize += 2 * sizeof (struct sockaddr_in6);
5777 
5778         rw_enter(&ipss->ipsec_alg_lock, RW_READER);
5779         /* NOTE:  The lock is now held through to this function's return. */
5780         allocsize += ipss->ipsec_nalgs[IPSEC_ALG_AUTH] *
5781             ipss->ipsec_nalgs[IPSEC_ALG_ENCR] * sizeof (sadb_comb_t);
5782 
5783         if (tunnel_mode) {
5784                 /* Tunnel mode! */
5785                 allocsize += 2 * sizeof (sadb_address_t);
5786                 /* Enough to cover both AF_INET and AF_INET6. */
5787                 allocsize += 2 * sizeof (struct sockaddr_in6);
5788         }
5789 
5790         msgmp = allocb(allocsize, BPRI_HI);
5791         if (msgmp == NULL) {
5792                 freeb(pfkeymp);
5793                 rw_exit(&ipss->ipsec_alg_lock);
5794                 return (NULL);
5795         }
5796 
5797         pfkeymp->b_cont = msgmp;
5798         cur = msgmp->b_rptr;
5799         end = cur + allocsize;
5800         samsg = (sadb_msg_t *)cur;
5801         cur += sizeof (sadb_msg_t);
5802 
5803         af = acqrec->ipsacq_addrfam;
5804         switch (af) {
5805         case AF_INET:
5806                 check_proto = IPPROTO_ICMP;
5807                 break;
5808         case AF_INET6:
5809                 check_proto = IPPROTO_ICMPV6;
5810                 break;
5811         default:
5812                 /* This should never happen unless we have kernel bugs. */
5813                 cmn_err(CE_WARN,
5814                     "sadb_setup_acquire:  corrupt ACQUIRE record.\n");
5815                 ASSERT(0);
5816                 rw_exit(&ipss->ipsec_alg_lock);
5817                 return (NULL);
5818         }
5819 
5820         samsg->sadb_msg_version = PF_KEY_V2;
5821         samsg->sadb_msg_type = SADB_ACQUIRE;
5822         samsg->sadb_msg_satype = satype;
5823         samsg->sadb_msg_errno = 0;
5824         samsg->sadb_msg_pid = 0;
5825         samsg->sadb_msg_reserved = 0;
5826         samsg->sadb_msg_seq = acqrec->ipsacq_seq;
5827 
5828         ASSERT(MUTEX_HELD(&acqrec->ipsacq_lock));
5829 
5830         if ((acqrec->ipsacq_proto == check_proto) || tunnel_mode) {
5831                 sport_typecode = dport_typecode = 0;
5832         } else {
5833                 sport_typecode = acqrec->ipsacq_srcport;
5834                 dport_typecode = acqrec->ipsacq_dstport;
5835         }
5836 


5843         if (tunnel_mode) {
5844                 sport_typecode = acqrec->ipsacq_srcport;
5845                 dport_typecode = acqrec->ipsacq_dstport;
5846                 cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_SRC,
5847                     acqrec->ipsacq_inneraddrfam, acqrec->ipsacq_innersrc,
5848                     sport_typecode, acqrec->ipsacq_inner_proto,
5849                     acqrec->ipsacq_innersrcpfx);
5850                 cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_DST,
5851                     acqrec->ipsacq_inneraddrfam, acqrec->ipsacq_innerdst,
5852                     dport_typecode, acqrec->ipsacq_inner_proto,
5853                     acqrec->ipsacq_innerdstpfx);
5854         }
5855 
5856         /* XXX Insert identity information here. */
5857 
5858         /* XXXMLS Insert sensitivity information here. */
5859 
5860         if (cur != NULL)
5861                 samsg->sadb_msg_len = SADB_8TO64(cur - msgmp->b_rptr);
5862         else
5863                 rw_exit(&ipss->ipsec_alg_lock);
5864 
5865         return (pfkeymp);
5866 }
5867 
5868 /*
5869  * Given an SADB_GETSPI message, find an appropriately ranged SA and
5870  * allocate an SA.  If there are message improprieties, return (ipsa_t *)-1.
5871  * If there was a memory allocation error, return NULL.  (Assume NULL !=
5872  * (ipsa_t *)-1).
5873  *
5874  * master_spi is passed in host order.
5875  */
5876 ipsa_t *
5877 sadb_getspi(keysock_in_t *ksi, uint32_t master_spi, int *diagnostic,
5878     netstack_t *ns, uint_t sa_type)
5879 {
5880         sadb_address_t *src =
5881             (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_SRC],
5882             *dst = (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_DST];
5883         sadb_spirange_t *range =


7174         SADB_ALG_UPDATE_WALK(espstack->esp_sadb.s_v4, sdb_if);
7175         SADB_ALG_UPDATE_WALK(espstack->esp_sadb.s_v6, sdb_of);
7176         SADB_ALG_UPDATE_WALK(espstack->esp_sadb.s_v6, sdb_if);
7177 }
7178 
7179 /*
7180  * Creates a context template for the specified SA. This function
7181  * is called when an SA is created and when a context template needs
7182  * to be created due to a change of software provider.
7183  */
7184 int
7185 ipsec_create_ctx_tmpl(ipsa_t *sa, ipsec_algtype_t alg_type)
7186 {
7187         ipsec_alginfo_t *alg;
7188         crypto_mechanism_t mech;
7189         crypto_key_t *key;
7190         crypto_ctx_template_t *sa_tmpl;
7191         int rv;
7192         ipsec_stack_t   *ipss = sa->ipsa_netstack->netstack_ipsec;
7193 
7194         ASSERT(RW_READ_HELD(&ipss->ipsec_alg_lock));
7195         ASSERT(MUTEX_HELD(&sa->ipsa_lock));
7196 
7197         /* get pointers to the algorithm info, context template, and key */
7198         switch (alg_type) {
7199         case IPSEC_ALG_AUTH:
7200                 key = &sa->ipsa_kcfauthkey;
7201                 sa_tmpl = &sa->ipsa_authtmpl;
7202                 alg = ipss->ipsec_alglists[alg_type][sa->ipsa_auth_alg];
7203                 break;
7204         case IPSEC_ALG_ENCR:
7205                 key = &sa->ipsa_kcfencrkey;
7206                 sa_tmpl = &sa->ipsa_encrtmpl;
7207                 alg = ipss->ipsec_alglists[alg_type][sa->ipsa_encr_alg];
7208                 break;
7209         default:
7210                 alg = NULL;
7211         }
7212 
7213         if (alg == NULL || !ALG_VALID(alg))
7214                 return (EINVAL);