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);
|