1 /* 2 * CDDL HEADER START 3 * 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 * Copyright 2017 Joyent, Inc. 26 */ 27 28 #include <sys/types.h> 29 #include <sys/stream.h> 30 #include <sys/stropts.h> 31 #include <sys/errno.h> 32 #include <sys/strlog.h> 33 #include <sys/tihdr.h> 34 #include <sys/socket.h> 35 #include <sys/ddi.h> 36 #include <sys/sunddi.h> 37 #include <sys/mkdev.h> 38 #include <sys/kmem.h> 39 #include <sys/zone.h> 40 #include <sys/sysmacros.h> 41 #include <sys/cmn_err.h> 42 #include <sys/vtrace.h> 43 #include <sys/debug.h> 44 #include <sys/atomic.h> 45 #include <sys/strsun.h> 46 #include <sys/random.h> 47 #include <netinet/in.h> 48 #include <net/if.h> 49 #include <netinet/ip6.h> 50 #include <netinet/icmp6.h> 51 #include <net/pfkeyv2.h> 52 #include <net/pfpolicy.h> 53 54 #include <inet/common.h> 55 #include <inet/mi.h> 56 #include <inet/ip.h> 57 #include <inet/ip6.h> 58 #include <inet/nd.h> 59 #include <inet/ip_if.h> 60 #include <inet/ip_ndp.h> 61 #include <inet/ipsec_info.h> 62 #include <inet/ipsec_impl.h> 63 #include <inet/sadb.h> 64 #include <inet/ipsecah.h> 65 #include <inet/ipsec_impl.h> 66 #include <inet/ipdrop.h> 67 #include <sys/taskq.h> 68 #include <sys/policy.h> 69 #include <sys/strsun.h> 70 71 #include <sys/crypto/common.h> 72 #include <sys/crypto/api.h> 73 #include <sys/kstat.h> 74 #include <sys/strsubr.h> 75 76 #include <sys/tsol/tnet.h> 77 78 /* 79 * Table of ND variables supported by ipsecah. These are loaded into 80 * ipsecah_g_nd in ipsecah_init_nd. 81 * All of these are alterable, within the min/max values given, at run time. 82 */ 83 static ipsecahparam_t lcl_param_arr[] = { 84 /* min max value name */ 85 { 0, 3, 0, "ipsecah_debug"}, 86 { 125, 32000, SADB_AGE_INTERVAL_DEFAULT, "ipsecah_age_interval"}, 87 { 1, 10, 1, "ipsecah_reap_delay"}, 88 { 1, SADB_MAX_REPLAY, 64, "ipsecah_replay_size"}, 89 { 1, 300, 15, "ipsecah_acquire_timeout"}, 90 { 1, 1800, 90, "ipsecah_larval_timeout"}, 91 /* Default lifetime values for ACQUIRE messages. */ 92 { 0, 0xffffffffU, 0, "ipsecah_default_soft_bytes"}, 93 { 0, 0xffffffffU, 0, "ipsecah_default_hard_bytes"}, 94 { 0, 0xffffffffU, 24000, "ipsecah_default_soft_addtime"}, 95 { 0, 0xffffffffU, 28800, "ipsecah_default_hard_addtime"}, 96 { 0, 0xffffffffU, 0, "ipsecah_default_soft_usetime"}, 97 { 0, 0xffffffffU, 0, "ipsecah_default_hard_usetime"}, 98 { 0, 1, 0, "ipsecah_log_unknown_spi"}, 99 }; 100 101 #define ah0dbg(a) printf a 102 /* NOTE: != 0 instead of > 0 so lint doesn't complain. */ 103 #define ah1dbg(ahstack, a) if (ahstack->ipsecah_debug != 0) printf a 104 #define ah2dbg(ahstack, a) if (ahstack->ipsecah_debug > 1) printf a 105 #define ah3dbg(ahstack, a) if (ahstack->ipsecah_debug > 2) printf a 106 107 /* 108 * XXX This is broken. Padding should be determined dynamically 109 * depending on the ICV size and IP version number so that the 110 * total AH header size is a multiple of 32 bits or 64 bits 111 * for V4 and V6 respectively. For 96bit ICVs we have no problems. 112 * Anything different from that, we need to fix our code. 113 */ 114 #define IPV4_PADDING_ALIGN 0x04 /* Multiple of 32 bits */ 115 #define IPV6_PADDING_ALIGN 0x04 /* Multiple of 32 bits */ 116 117 /* 118 * Helper macro. Avoids a call to msgdsize if there is only one 119 * mblk in the chain. 120 */ 121 #define AH_MSGSIZE(mp) ((mp)->b_cont != NULL ? msgdsize(mp) : MBLKL(mp)) 122 123 124 static mblk_t *ah_auth_out_done(mblk_t *, ip_xmit_attr_t *, ipsec_crypto_t *); 125 static mblk_t *ah_auth_in_done(mblk_t *, ip_recv_attr_t *, ipsec_crypto_t *); 126 static mblk_t *ah_process_ip_options_v4(mblk_t *, ipsa_t *, int *, uint_t, 127 boolean_t, ipsecah_stack_t *); 128 static mblk_t *ah_process_ip_options_v6(mblk_t *, ipsa_t *, int *, uint_t, 129 boolean_t, ipsecah_stack_t *); 130 static void ah_getspi(mblk_t *, keysock_in_t *, ipsecah_stack_t *); 131 static void ah_inbound_restart(mblk_t *, ip_recv_attr_t *); 132 133 static mblk_t *ah_outbound(mblk_t *, ip_xmit_attr_t *); 134 static void ah_outbound_finish(mblk_t *, ip_xmit_attr_t *); 135 136 static int ipsecah_open(queue_t *, dev_t *, int, int, cred_t *); 137 static int ipsecah_close(queue_t *, int, cred_t *); 138 static int ipsecah_rput(queue_t *, mblk_t *); 139 static int ipsecah_wput(queue_t *, mblk_t *); 140 static boolean_t ah_register_out(uint32_t, uint32_t, uint_t, ipsecah_stack_t *, 141 cred_t *); 142 static void *ipsecah_stack_init(netstackid_t stackid, netstack_t *ns); 143 static void ipsecah_stack_fini(netstackid_t stackid, void *arg); 144 145 /* Setable in /etc/system */ 146 uint32_t ah_hash_size = IPSEC_DEFAULT_HASH_SIZE; 147 148 static taskq_t *ah_taskq; 149 150 static struct module_info info = { 151 5136, "ipsecah", 0, INFPSZ, 65536, 1024 152 }; 153 154 static struct qinit rinit = { 155 ipsecah_rput, NULL, ipsecah_open, ipsecah_close, NULL, &info, 156 NULL 157 }; 158 159 static struct qinit winit = { 160 ipsecah_wput, NULL, ipsecah_open, ipsecah_close, NULL, &info, 161 NULL 162 }; 163 164 struct streamtab ipsecahinfo = { 165 &rinit, &winit, NULL, NULL 166 }; 167 168 static int ah_kstat_update(kstat_t *, int); 169 170 uint64_t ipsacq_maxpackets = IPSACQ_MAXPACKETS; 171 172 static boolean_t 173 ah_kstat_init(ipsecah_stack_t *ahstack, netstackid_t stackid) 174 { 175 ipsec_stack_t *ipss = ahstack->ipsecah_netstack->netstack_ipsec; 176 177 ahstack->ah_ksp = kstat_create_netstack("ipsecah", 0, "ah_stat", "net", 178 KSTAT_TYPE_NAMED, sizeof (ah_kstats_t) / sizeof (kstat_named_t), 0, 179 stackid); 180 181 if (ahstack->ah_ksp == NULL || ahstack->ah_ksp->ks_data == NULL) 182 return (B_FALSE); 183 184 ahstack->ah_kstats = ahstack->ah_ksp->ks_data; 185 186 ahstack->ah_ksp->ks_update = ah_kstat_update; 187 ahstack->ah_ksp->ks_private = (void *)(uintptr_t)stackid; 188 189 #define K64 KSTAT_DATA_UINT64 190 #define KI(x) kstat_named_init(&(ahstack->ah_kstats->ah_stat_##x), #x, K64) 191 192 KI(num_aalgs); 193 KI(good_auth); 194 KI(bad_auth); 195 KI(replay_failures); 196 KI(replay_early_failures); 197 KI(keysock_in); 198 KI(out_requests); 199 KI(acquire_requests); 200 KI(bytes_expired); 201 KI(out_discards); 202 KI(crypto_sync); 203 KI(crypto_async); 204 KI(crypto_failures); 205 206 #undef KI 207 #undef K64 208 209 kstat_install(ahstack->ah_ksp); 210 IP_ACQUIRE_STAT(ipss, maxpackets, ipsacq_maxpackets); 211 return (B_TRUE); 212 } 213 214 static int 215 ah_kstat_update(kstat_t *kp, int rw) 216 { 217 ah_kstats_t *ekp; 218 netstackid_t stackid = (netstackid_t)(uintptr_t)kp->ks_private; 219 netstack_t *ns; 220 ipsec_stack_t *ipss; 221 222 if ((kp == NULL) || (kp->ks_data == NULL)) 223 return (EIO); 224 225 if (rw == KSTAT_WRITE) 226 return (EACCES); 227 228 ns = netstack_find_by_stackid(stackid); 229 if (ns == NULL) 230 return (-1); 231 ipss = ns->netstack_ipsec; 232 if (ipss == NULL) { 233 netstack_rele(ns); 234 return (-1); 235 } 236 ekp = (ah_kstats_t *)kp->ks_data; 237 238 rw_enter(&ipss->ipsec_alg_lock, RW_READER); 239 ekp->ah_stat_num_aalgs.value.ui64 = ipss->ipsec_nalgs[IPSEC_ALG_AUTH]; 240 rw_exit(&ipss->ipsec_alg_lock); 241 242 netstack_rele(ns); 243 return (0); 244 } 245 246 /* 247 * Don't have to lock ipsec_age_interval, as only one thread will access it at 248 * a time, because I control the one function that does a qtimeout() on 249 * ah_pfkey_q. 250 */ 251 static void 252 ah_ager(void *arg) 253 { 254 ipsecah_stack_t *ahstack = (ipsecah_stack_t *)arg; 255 netstack_t *ns = ahstack->ipsecah_netstack; 256 hrtime_t begin = gethrtime(); 257 258 sadb_ager(&ahstack->ah_sadb.s_v4, ahstack->ah_pfkey_q, 259 ahstack->ipsecah_reap_delay, ns); 260 sadb_ager(&ahstack->ah_sadb.s_v6, ahstack->ah_pfkey_q, 261 ahstack->ipsecah_reap_delay, ns); 262 263 ahstack->ah_event = sadb_retimeout(begin, ahstack->ah_pfkey_q, 264 ah_ager, ahstack, 265 &ahstack->ipsecah_age_interval, ahstack->ipsecah_age_int_max, 266 info.mi_idnum); 267 } 268 269 /* 270 * Get an AH NDD parameter. 271 */ 272 /* ARGSUSED */ 273 static int 274 ipsecah_param_get( 275 queue_t *q, 276 mblk_t *mp, 277 caddr_t cp, 278 cred_t *cr) 279 { 280 ipsecahparam_t *ipsecahpa = (ipsecahparam_t *)cp; 281 uint_t value; 282 ipsecah_stack_t *ahstack = (ipsecah_stack_t *)q->q_ptr; 283 284 mutex_enter(&ahstack->ipsecah_param_lock); 285 value = ipsecahpa->ipsecah_param_value; 286 mutex_exit(&ahstack->ipsecah_param_lock); 287 288 (void) mi_mpprintf(mp, "%u", value); 289 return (0); 290 } 291 292 /* 293 * This routine sets an NDD variable in a ipsecahparam_t structure. 294 */ 295 /* ARGSUSED */ 296 static int 297 ipsecah_param_set( 298 queue_t *q, 299 mblk_t *mp, 300 char *value, 301 caddr_t cp, 302 cred_t *cr) 303 { 304 ulong_t new_value; 305 ipsecahparam_t *ipsecahpa = (ipsecahparam_t *)cp; 306 ipsecah_stack_t *ahstack = (ipsecah_stack_t *)q->q_ptr; 307 308 /* 309 * Fail the request if the new value does not lie within the 310 * required bounds. 311 */ 312 if (ddi_strtoul(value, NULL, 10, &new_value) != 0 || 313 new_value < ipsecahpa->ipsecah_param_min || 314 new_value > ipsecahpa->ipsecah_param_max) { 315 return (EINVAL); 316 } 317 318 /* Set the new value */ 319 mutex_enter(&ahstack->ipsecah_param_lock); 320 ipsecahpa->ipsecah_param_value = new_value; 321 mutex_exit(&ahstack->ipsecah_param_lock); 322 return (0); 323 } 324 325 /* 326 * Using lifetime NDD variables, fill in an extended combination's 327 * lifetime information. 328 */ 329 void 330 ipsecah_fill_defs(sadb_x_ecomb_t *ecomb, netstack_t *ns) 331 { 332 ipsecah_stack_t *ahstack = ns->netstack_ipsecah; 333 334 ecomb->sadb_x_ecomb_soft_bytes = ahstack->ipsecah_default_soft_bytes; 335 ecomb->sadb_x_ecomb_hard_bytes = ahstack->ipsecah_default_hard_bytes; 336 ecomb->sadb_x_ecomb_soft_addtime = 337 ahstack->ipsecah_default_soft_addtime; 338 ecomb->sadb_x_ecomb_hard_addtime = 339 ahstack->ipsecah_default_hard_addtime; 340 ecomb->sadb_x_ecomb_soft_usetime = 341 ahstack->ipsecah_default_soft_usetime; 342 ecomb->sadb_x_ecomb_hard_usetime = 343 ahstack->ipsecah_default_hard_usetime; 344 } 345 346 /* 347 * Initialize things for AH at module load time. 348 */ 349 boolean_t 350 ipsecah_ddi_init(void) 351 { 352 ah_taskq = taskq_create("ah_taskq", 1, minclsyspri, 353 IPSEC_TASKQ_MIN, IPSEC_TASKQ_MAX, 0); 354 355 /* 356 * We want to be informed each time a stack is created or 357 * destroyed in the kernel, so we can maintain the 358 * set of ipsecah_stack_t's. 359 */ 360 netstack_register(NS_IPSECAH, ipsecah_stack_init, NULL, 361 ipsecah_stack_fini); 362 363 return (B_TRUE); 364 } 365 366 /* 367 * Walk through the param array specified registering each element with the 368 * named dispatch handler. 369 */ 370 static boolean_t 371 ipsecah_param_register(IDP *ndp, ipsecahparam_t *ahp, int cnt) 372 { 373 for (; cnt-- > 0; ahp++) { 374 if (ahp->ipsecah_param_name != NULL && 375 ahp->ipsecah_param_name[0]) { 376 if (!nd_load(ndp, 377 ahp->ipsecah_param_name, 378 ipsecah_param_get, ipsecah_param_set, 379 (caddr_t)ahp)) { 380 nd_free(ndp); 381 return (B_FALSE); 382 } 383 } 384 } 385 return (B_TRUE); 386 } 387 388 /* 389 * Initialize things for AH for each stack instance 390 */ 391 static void * 392 ipsecah_stack_init(netstackid_t stackid, netstack_t *ns) 393 { 394 ipsecah_stack_t *ahstack; 395 ipsecahparam_t *ahp; 396 397 ahstack = (ipsecah_stack_t *)kmem_zalloc(sizeof (*ahstack), KM_SLEEP); 398 ahstack->ipsecah_netstack = ns; 399 400 ahp = (ipsecahparam_t *)kmem_alloc(sizeof (lcl_param_arr), KM_SLEEP); 401 ahstack->ipsecah_params = ahp; 402 bcopy(lcl_param_arr, ahp, sizeof (lcl_param_arr)); 403 404 (void) ipsecah_param_register(&ahstack->ipsecah_g_nd, ahp, 405 A_CNT(lcl_param_arr)); 406 407 (void) ah_kstat_init(ahstack, stackid); 408 409 ahstack->ah_sadb.s_acquire_timeout = &ahstack->ipsecah_acquire_timeout; 410 sadbp_init("AH", &ahstack->ah_sadb, SADB_SATYPE_AH, ah_hash_size, 411 ahstack->ipsecah_netstack); 412 413 mutex_init(&ahstack->ipsecah_param_lock, NULL, MUTEX_DEFAULT, 0); 414 415 ip_drop_register(&ahstack->ah_dropper, "IPsec AH"); 416 return (ahstack); 417 } 418 419 /* 420 * Destroy things for AH at module unload time. 421 */ 422 void 423 ipsecah_ddi_destroy(void) 424 { 425 netstack_unregister(NS_IPSECAH); 426 taskq_destroy(ah_taskq); 427 } 428 429 /* 430 * Destroy things for AH for one stack... Never called? 431 */ 432 static void 433 ipsecah_stack_fini(netstackid_t stackid, void *arg) 434 { 435 ipsecah_stack_t *ahstack = (ipsecah_stack_t *)arg; 436 437 if (ahstack->ah_pfkey_q != NULL) { 438 (void) quntimeout(ahstack->ah_pfkey_q, ahstack->ah_event); 439 } 440 ahstack->ah_sadb.s_acquire_timeout = NULL; 441 sadbp_destroy(&ahstack->ah_sadb, ahstack->ipsecah_netstack); 442 ip_drop_unregister(&ahstack->ah_dropper); 443 mutex_destroy(&ahstack->ipsecah_param_lock); 444 nd_free(&ahstack->ipsecah_g_nd); 445 446 kmem_free(ahstack->ipsecah_params, sizeof (lcl_param_arr)); 447 ahstack->ipsecah_params = NULL; 448 kstat_delete_netstack(ahstack->ah_ksp, stackid); 449 ahstack->ah_ksp = NULL; 450 ahstack->ah_kstats = NULL; 451 452 kmem_free(ahstack, sizeof (*ahstack)); 453 } 454 455 /* 456 * AH module open routine, which is here for keysock plumbing. 457 * Keysock is pushed over {AH,ESP} which is an artifact from the Bad Old 458 * Days of export control, and fears that ESP would not be allowed 459 * to be shipped at all by default. Eventually, keysock should 460 * either access AH and ESP via modstubs or krtld dependencies, or 461 * perhaps be folded in with AH and ESP into a single IPsec/netsec 462 * module ("netsec" if PF_KEY provides more than AH/ESP keying tables). 463 */ 464 /* ARGSUSED */ 465 static int 466 ipsecah_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp) 467 { 468 netstack_t *ns; 469 ipsecah_stack_t *ahstack; 470 471 if (secpolicy_ip_config(credp, B_FALSE) != 0) 472 return (EPERM); 473 474 if (q->q_ptr != NULL) 475 return (0); /* Re-open of an already open instance. */ 476 477 if (sflag != MODOPEN) 478 return (EINVAL); 479 480 ns = netstack_find_by_cred(credp); 481 ASSERT(ns != NULL); 482 ahstack = ns->netstack_ipsecah; 483 ASSERT(ahstack != NULL); 484 485 q->q_ptr = ahstack; 486 WR(q)->q_ptr = q->q_ptr; 487 488 qprocson(q); 489 return (0); 490 } 491 492 /* 493 * AH module close routine. 494 */ 495 /* ARGSUSED */ 496 static int 497 ipsecah_close(queue_t *q, int flags __unused, cred_t *credp __unused) 498 { 499 ipsecah_stack_t *ahstack = (ipsecah_stack_t *)q->q_ptr; 500 501 /* 502 * Clean up q_ptr, if needed. 503 */ 504 qprocsoff(q); 505 506 /* Keysock queue check is safe, because of OCEXCL perimeter. */ 507 508 if (q == ahstack->ah_pfkey_q) { 509 ah1dbg(ahstack, 510 ("ipsecah_close: Ummm... keysock is closing AH.\n")); 511 ahstack->ah_pfkey_q = NULL; 512 /* Detach qtimeouts. */ 513 (void) quntimeout(q, ahstack->ah_event); 514 } 515 516 netstack_rele(ahstack->ipsecah_netstack); 517 return (0); 518 } 519 520 /* 521 * Construct an SADB_REGISTER message with the current algorithms. 522 */ 523 static boolean_t 524 ah_register_out(uint32_t sequence, uint32_t pid, uint_t serial, 525 ipsecah_stack_t *ahstack, cred_t *cr) 526 { 527 mblk_t *mp; 528 boolean_t rc = B_TRUE; 529 sadb_msg_t *samsg; 530 sadb_supported_t *sasupp; 531 sadb_alg_t *saalg; 532 uint_t allocsize = sizeof (*samsg); 533 uint_t i, numalgs_snap; 534 ipsec_alginfo_t **authalgs; 535 uint_t num_aalgs; 536 ipsec_stack_t *ipss = ahstack->ipsecah_netstack->netstack_ipsec; 537 sadb_sens_t *sens; 538 size_t sens_len = 0; 539 sadb_ext_t *nextext; 540 ts_label_t *sens_tsl = NULL; 541 542 /* Allocate the KEYSOCK_OUT. */ 543 mp = sadb_keysock_out(serial); 544 if (mp == NULL) { 545 ah0dbg(("ah_register_out: couldn't allocate mblk.\n")); 546 return (B_FALSE); 547 } 548 549 if (is_system_labeled() && (cr != NULL)) { 550 sens_tsl = crgetlabel(cr); 551 if (sens_tsl != NULL) { 552 sens_len = sadb_sens_len_from_label(sens_tsl); 553 allocsize += sens_len; 554 } 555 } 556 557 /* 558 * Allocate the PF_KEY message that follows KEYSOCK_OUT. 559 * The alg reader lock needs to be held while allocating 560 * the variable part (i.e. the algorithms) of the message. 561 */ 562 563 rw_enter(&ipss->ipsec_alg_lock, RW_READER); 564 565 /* 566 * Return only valid algorithms, so the number of algorithms 567 * to send up may be less than the number of algorithm entries 568 * in the table. 569 */ 570 authalgs = ipss->ipsec_alglists[IPSEC_ALG_AUTH]; 571 for (num_aalgs = 0, i = 0; i < IPSEC_MAX_ALGS; i++) 572 if (authalgs[i] != NULL && ALG_VALID(authalgs[i])) 573 num_aalgs++; 574 575 /* 576 * Fill SADB_REGISTER message's algorithm descriptors. Hold 577 * down the lock while filling it. 578 */ 579 if (num_aalgs != 0) { 580 allocsize += (num_aalgs * sizeof (*saalg)); 581 allocsize += sizeof (*sasupp); 582 } 583 mp->b_cont = allocb(allocsize, BPRI_HI); 584 if (mp->b_cont == NULL) { 585 rw_exit(&ipss->ipsec_alg_lock); 586 freemsg(mp); 587 return (B_FALSE); 588 } 589 590 mp->b_cont->b_wptr += allocsize; 591 nextext = (sadb_ext_t *)(mp->b_cont->b_rptr + sizeof (*samsg)); 592 593 if (num_aalgs != 0) { 594 595 saalg = (sadb_alg_t *)(((uint8_t *)nextext) + sizeof (*sasupp)); 596 ASSERT(((ulong_t)saalg & 0x7) == 0); 597 598 numalgs_snap = 0; 599 for (i = 0; 600 ((i < IPSEC_MAX_ALGS) && (numalgs_snap < num_aalgs)); 601 i++) { 602 if (authalgs[i] == NULL || !ALG_VALID(authalgs[i])) 603 continue; 604 605 saalg->sadb_alg_id = authalgs[i]->alg_id; 606 saalg->sadb_alg_ivlen = 0; 607 saalg->sadb_alg_minbits = authalgs[i]->alg_ef_minbits; 608 saalg->sadb_alg_maxbits = authalgs[i]->alg_ef_maxbits; 609 saalg->sadb_x_alg_increment = 610 authalgs[i]->alg_increment; 611 /* For now, salt is meaningless in AH. */ 612 ASSERT(authalgs[i]->alg_saltlen == 0); 613 saalg->sadb_x_alg_saltbits = 614 SADB_8TO1(authalgs[i]->alg_saltlen); 615 numalgs_snap++; 616 saalg++; 617 } 618 ASSERT(numalgs_snap == num_aalgs); 619 #ifdef DEBUG 620 /* 621 * Reality check to make sure I snagged all of the 622 * algorithms. 623 */ 624 for (; i < IPSEC_MAX_ALGS; i++) 625 if (authalgs[i] != NULL && ALG_VALID(authalgs[i])) 626 cmn_err(CE_PANIC, 627 "ah_register_out()! Missed #%d.\n", i); 628 #endif /* DEBUG */ 629 nextext = (sadb_ext_t *)saalg; 630 } 631 632 rw_exit(&ipss->ipsec_alg_lock); 633 634 if (sens_tsl != NULL) { 635 sens = (sadb_sens_t *)nextext; 636 sadb_sens_from_label(sens, SADB_EXT_SENSITIVITY, 637 sens_tsl, sens_len); 638 639 nextext = (sadb_ext_t *)(((uint8_t *)sens) + sens_len); 640 } 641 642 /* Now fill the restof the SADB_REGISTER message. */ 643 644 samsg = (sadb_msg_t *)mp->b_cont->b_rptr; 645 samsg->sadb_msg_version = PF_KEY_V2; 646 samsg->sadb_msg_type = SADB_REGISTER; 647 samsg->sadb_msg_errno = 0; 648 samsg->sadb_msg_satype = SADB_SATYPE_AH; 649 samsg->sadb_msg_len = SADB_8TO64(allocsize); 650 samsg->sadb_msg_reserved = 0; 651 /* 652 * Assume caller has sufficient sequence/pid number info. If it's one 653 * from me over a new alg., I could give two hoots about sequence. 654 */ 655 samsg->sadb_msg_seq = sequence; 656 samsg->sadb_msg_pid = pid; 657 658 if (num_aalgs != 0) { 659 sasupp = (sadb_supported_t *)(samsg + 1); 660 sasupp->sadb_supported_len = SADB_8TO64( 661 sizeof (*sasupp) + sizeof (*saalg) * num_aalgs); 662 sasupp->sadb_supported_exttype = SADB_EXT_SUPPORTED_AUTH; 663 sasupp->sadb_supported_reserved = 0; 664 } 665 666 if (ahstack->ah_pfkey_q != NULL) 667 putnext(ahstack->ah_pfkey_q, mp); 668 else { 669 rc = B_FALSE; 670 freemsg(mp); 671 } 672 673 return (rc); 674 } 675 676 /* 677 * Invoked when the algorithm table changes. Causes SADB_REGISTER 678 * messages continaining the current list of algorithms to be 679 * sent up to the AH listeners. 680 */ 681 void 682 ipsecah_algs_changed(netstack_t *ns) 683 { 684 ipsecah_stack_t *ahstack = ns->netstack_ipsecah; 685 686 /* 687 * Time to send a PF_KEY SADB_REGISTER message to AH listeners 688 * everywhere. (The function itself checks for NULL ah_pfkey_q.) 689 */ 690 (void) ah_register_out(0, 0, 0, ahstack, NULL); 691 } 692 693 /* 694 * Stub function that taskq_dispatch() invokes to take the mblk (in arg) 695 * and send it into AH and IP again. 696 */ 697 static void 698 inbound_task(void *arg) 699 { 700 mblk_t *mp = (mblk_t *)arg; 701 mblk_t *async_mp; 702 ip_recv_attr_t iras; 703 704 async_mp = mp; 705 mp = async_mp->b_cont; 706 async_mp->b_cont = NULL; 707 if (!ip_recv_attr_from_mblk(async_mp, &iras)) { 708 /* The ill or ip_stack_t disappeared on us */ 709 ip_drop_input("ip_recv_attr_from_mblk", mp, NULL); 710 freemsg(mp); 711 goto done; 712 } 713 714 ah_inbound_restart(mp, &iras); 715 done: 716 ira_cleanup(&iras, B_TRUE); 717 } 718 719 /* 720 * Restart ESP after the SA has been added. 721 */ 722 static void 723 ah_inbound_restart(mblk_t *mp, ip_recv_attr_t *ira) 724 { 725 ah_t *ah; 726 netstack_t *ns; 727 ipsecah_stack_t *ahstack; 728 729 ns = ira->ira_ill->ill_ipst->ips_netstack; 730 ahstack = ns->netstack_ipsecah; 731 732 ASSERT(ahstack != NULL); 733 mp = ipsec_inbound_ah_sa(mp, ira, &ah); 734 if (mp == NULL) 735 return; 736 737 ASSERT(ah != NULL); 738 ASSERT(ira->ira_flags & IRAF_IPSEC_SECURE); 739 ASSERT(ira->ira_ipsec_ah_sa != NULL); 740 741 mp = ira->ira_ipsec_ah_sa->ipsa_input_func(mp, ah, ira); 742 if (mp == NULL) { 743 /* 744 * Either it failed or is pending. In the former case 745 * ipIfStatsInDiscards was increased. 746 */ 747 return; 748 } 749 ip_input_post_ipsec(mp, ira); 750 } 751 752 /* 753 * Now that weak-key passed, actually ADD the security association, and 754 * send back a reply ADD message. 755 */ 756 static int 757 ah_add_sa_finish(mblk_t *mp, sadb_msg_t *samsg, keysock_in_t *ksi, 758 int *diagnostic, ipsecah_stack_t *ahstack) 759 { 760 isaf_t *primary = NULL, *secondary; 761 boolean_t clone = B_FALSE, is_inbound = B_FALSE; 762 sadb_sa_t *assoc = (sadb_sa_t *)ksi->ks_in_extv[SADB_EXT_SA]; 763 ipsa_t *larval; 764 ipsacq_t *acqrec; 765 iacqf_t *acq_bucket; 766 mblk_t *acq_msgs = NULL; 767 mblk_t *lpkt; 768 int rc; 769 ipsa_query_t sq; 770 int error; 771 netstack_t *ns = ahstack->ipsecah_netstack; 772 ipsec_stack_t *ipss = ns->netstack_ipsec; 773 774 /* 775 * Locate the appropriate table(s). 776 */ 777 778 sq.spp = &ahstack->ah_sadb; 779 error = sadb_form_query(ksi, IPSA_Q_SA|IPSA_Q_DST, 780 IPSA_Q_SA|IPSA_Q_DST|IPSA_Q_INBOUND|IPSA_Q_OUTBOUND, 781 &sq, diagnostic); 782 if (error) 783 return (error); 784 785 /* 786 * Use the direction flags provided by the KMD to determine 787 * if the inbound or outbound table should be the primary 788 * for this SA. If these flags were absent then make this 789 * decision based on the addresses. 790 */ 791 if (assoc->sadb_sa_flags & IPSA_F_INBOUND) { 792 primary = sq.inbound; 793 secondary = sq.outbound; 794 is_inbound = B_TRUE; 795 if (assoc->sadb_sa_flags & IPSA_F_OUTBOUND) 796 clone = B_TRUE; 797 } else { 798 if (assoc->sadb_sa_flags & IPSA_F_OUTBOUND) { 799 primary = sq.outbound; 800 secondary = sq.inbound; 801 } 802 } 803 if (primary == NULL) { 804 /* 805 * The KMD did not set a direction flag, determine which 806 * table to insert the SA into based on addresses. 807 */ 808 switch (ksi->ks_in_dsttype) { 809 case KS_IN_ADDR_MBCAST: 810 clone = B_TRUE; /* All mcast SAs can be bidirectional */ 811 assoc->sadb_sa_flags |= IPSA_F_OUTBOUND; 812 /* FALLTHRU */ 813 /* 814 * If the source address is either one of mine, or unspecified 815 * (which is best summed up by saying "not 'not mine'"), 816 * then the association is potentially bi-directional, 817 * in that it can be used for inbound traffic and outbound 818 * traffic. The best example of such and SA is a multicast 819 * SA (which allows me to receive the outbound traffic). 820 */ 821 case KS_IN_ADDR_ME: 822 assoc->sadb_sa_flags |= IPSA_F_INBOUND; 823 primary = sq.inbound; 824 secondary = sq.outbound; 825 if (ksi->ks_in_srctype != KS_IN_ADDR_NOTME) 826 clone = B_TRUE; 827 is_inbound = B_TRUE; 828 break; 829 830 /* 831 * If the source address literally not mine (either 832 * unspecified or not mine), then this SA may have an 833 * address that WILL be mine after some configuration. 834 * We pay the price for this by making it a bi-directional 835 * SA. 836 */ 837 case KS_IN_ADDR_NOTME: 838 assoc->sadb_sa_flags |= IPSA_F_OUTBOUND; 839 primary = sq.outbound; 840 secondary = sq.inbound; 841 if (ksi->ks_in_srctype != KS_IN_ADDR_ME) { 842 assoc->sadb_sa_flags |= IPSA_F_INBOUND; 843 clone = B_TRUE; 844 } 845 break; 846 default: 847 *diagnostic = SADB_X_DIAGNOSTIC_BAD_DST; 848 return (EINVAL); 849 } 850 } 851 852 /* 853 * Find a ACQUIRE list entry if possible. If we've added an SA that 854 * suits the needs of an ACQUIRE list entry, we can eliminate the 855 * ACQUIRE list entry and transmit the enqueued packets. Use the 856 * high-bit of the sequence number to queue it. Key off destination 857 * addr, and change acqrec's state. 858 */ 859 860 if (samsg->sadb_msg_seq & IACQF_LOWEST_SEQ) { 861 acq_bucket = &(sq.sp->sdb_acq[sq.outhash]); 862 mutex_enter(&acq_bucket->iacqf_lock); 863 for (acqrec = acq_bucket->iacqf_ipsacq; acqrec != NULL; 864 acqrec = acqrec->ipsacq_next) { 865 mutex_enter(&acqrec->ipsacq_lock); 866 /* 867 * Q: I only check sequence. Should I check dst? 868 * A: Yes, check dest because those are the packets 869 * that are queued up. 870 */ 871 if (acqrec->ipsacq_seq == samsg->sadb_msg_seq && 872 IPSA_ARE_ADDR_EQUAL(sq.dstaddr, 873 acqrec->ipsacq_dstaddr, acqrec->ipsacq_addrfam)) 874 break; 875 mutex_exit(&acqrec->ipsacq_lock); 876 } 877 if (acqrec != NULL) { 878 /* 879 * AHA! I found an ACQUIRE record for this SA. 880 * Grab the msg list, and free the acquire record. 881 * I already am holding the lock for this record, 882 * so all I have to do is free it. 883 */ 884 acq_msgs = acqrec->ipsacq_mp; 885 acqrec->ipsacq_mp = NULL; 886 mutex_exit(&acqrec->ipsacq_lock); 887 sadb_destroy_acquire(acqrec, ns); 888 } 889 mutex_exit(&acq_bucket->iacqf_lock); 890 } 891 892 /* 893 * Find PF_KEY message, and see if I'm an update. If so, find entry 894 * in larval list (if there). 895 */ 896 897 larval = NULL; 898 899 if (samsg->sadb_msg_type == SADB_UPDATE) { 900 mutex_enter(&sq.inbound->isaf_lock); 901 larval = ipsec_getassocbyspi(sq.inbound, sq.assoc->sadb_sa_spi, 902 ALL_ZEROES_PTR, sq.dstaddr, sq.dst->sin_family); 903 mutex_exit(&sq.inbound->isaf_lock); 904 905 if ((larval == NULL) || 906 (larval->ipsa_state != IPSA_STATE_LARVAL)) { 907 *diagnostic = SADB_X_DIAGNOSTIC_SA_NOTFOUND; 908 if (larval != NULL) { 909 IPSA_REFRELE(larval); 910 } 911 ah0dbg(("Larval update, but larval disappeared.\n")); 912 return (ESRCH); 913 } /* Else sadb_common_add unlinks it for me! */ 914 } 915 916 if (larval != NULL) { 917 /* 918 * Hold again, because sadb_common_add() consumes a reference, 919 * and we don't want to clear_lpkt() without a reference. 920 */ 921 IPSA_REFHOLD(larval); 922 } 923 924 rc = sadb_common_add(ahstack->ah_pfkey_q, mp, 925 samsg, ksi, primary, secondary, larval, clone, is_inbound, 926 diagnostic, ns, &ahstack->ah_sadb); 927 928 if (larval != NULL) { 929 if (rc == 0) { 930 lpkt = sadb_clear_lpkt(larval); 931 if (lpkt != NULL) { 932 rc = !taskq_dispatch(ah_taskq, inbound_task, 933 lpkt, TQ_NOSLEEP); 934 } 935 } 936 IPSA_REFRELE(larval); 937 } 938 939 /* 940 * How much more stack will I create with all of these 941 * ah_outbound_*() calls? 942 */ 943 944 /* Handle the packets queued waiting for the SA */ 945 while (acq_msgs != NULL) { 946 mblk_t *asyncmp; 947 mblk_t *data_mp; 948 ip_xmit_attr_t ixas; 949 ill_t *ill; 950 951 asyncmp = acq_msgs; 952 acq_msgs = acq_msgs->b_next; 953 asyncmp->b_next = NULL; 954 955 /* 956 * Extract the ip_xmit_attr_t from the first mblk. 957 * Verifies that the netstack and ill is still around; could 958 * have vanished while iked was doing its work. 959 * On succesful return we have a nce_t and the ill/ipst can't 960 * disappear until we do the nce_refrele in ixa_cleanup. 961 */ 962 data_mp = asyncmp->b_cont; 963 asyncmp->b_cont = NULL; 964 if (!ip_xmit_attr_from_mblk(asyncmp, &ixas)) { 965 AH_BUMP_STAT(ahstack, out_discards); 966 ip_drop_packet(data_mp, B_FALSE, NULL, 967 DROPPER(ipss, ipds_sadb_acquire_timeout), 968 &ahstack->ah_dropper); 969 } else if (rc != 0) { 970 ill = ixas.ixa_nce->nce_ill; 971 AH_BUMP_STAT(ahstack, out_discards); 972 ip_drop_packet(data_mp, B_FALSE, ill, 973 DROPPER(ipss, ipds_sadb_acquire_timeout), 974 &ahstack->ah_dropper); 975 BUMP_MIB(ill->ill_ip_mib, ipIfStatsOutDiscards); 976 } else { 977 ah_outbound_finish(data_mp, &ixas); 978 } 979 ixa_cleanup(&ixas); 980 } 981 982 return (rc); 983 } 984 985 986 /* 987 * Process one of the queued messages (from ipsacq_mp) once the SA 988 * has been added. 989 */ 990 static void 991 ah_outbound_finish(mblk_t *data_mp, ip_xmit_attr_t *ixa) 992 { 993 netstack_t *ns = ixa->ixa_ipst->ips_netstack; 994 ipsecah_stack_t *ahstack = ns->netstack_ipsecah; 995 ipsec_stack_t *ipss = ns->netstack_ipsec; 996 ill_t *ill = ixa->ixa_nce->nce_ill; 997 998 if (!ipsec_outbound_sa(data_mp, ixa, IPPROTO_AH)) { 999 AH_BUMP_STAT(ahstack, out_discards); 1000 ip_drop_packet(data_mp, B_FALSE, ill, 1001 DROPPER(ipss, ipds_sadb_acquire_timeout), 1002 &ahstack->ah_dropper); 1003 BUMP_MIB(ill->ill_ip_mib, ipIfStatsOutDiscards); 1004 return; 1005 } 1006 1007 data_mp = ah_outbound(data_mp, ixa); 1008 if (data_mp == NULL) 1009 return; 1010 1011 (void) ip_output_post_ipsec(data_mp, ixa); 1012 } 1013 1014 /* 1015 * Add new AH security association. This may become a generic AH/ESP 1016 * routine eventually. 1017 */ 1018 static int 1019 ah_add_sa(mblk_t *mp, keysock_in_t *ksi, int *diagnostic, netstack_t *ns) 1020 { 1021 sadb_sa_t *assoc = (sadb_sa_t *)ksi->ks_in_extv[SADB_EXT_SA]; 1022 sadb_address_t *srcext = 1023 (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_SRC]; 1024 sadb_address_t *dstext = 1025 (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_DST]; 1026 sadb_address_t *isrcext = 1027 (sadb_address_t *)ksi->ks_in_extv[SADB_X_EXT_ADDRESS_INNER_SRC]; 1028 sadb_address_t *idstext = 1029 (sadb_address_t *)ksi->ks_in_extv[SADB_X_EXT_ADDRESS_INNER_DST]; 1030 sadb_key_t *key = (sadb_key_t *)ksi->ks_in_extv[SADB_EXT_KEY_AUTH]; 1031 struct sockaddr_in *src, *dst; 1032 /* We don't need sockaddr_in6 for now. */ 1033 sadb_lifetime_t *soft = 1034 (sadb_lifetime_t *)ksi->ks_in_extv[SADB_EXT_LIFETIME_SOFT]; 1035 sadb_lifetime_t *hard = 1036 (sadb_lifetime_t *)ksi->ks_in_extv[SADB_EXT_LIFETIME_HARD]; 1037 sadb_lifetime_t *idle = 1038 (sadb_lifetime_t *)ksi->ks_in_extv[SADB_X_EXT_LIFETIME_IDLE]; 1039 ipsec_alginfo_t *aalg; 1040 ipsecah_stack_t *ahstack = ns->netstack_ipsecah; 1041 ipsec_stack_t *ipss = ns->netstack_ipsec; 1042 1043 /* I need certain extensions present for an ADD message. */ 1044 if (srcext == NULL) { 1045 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_SRC; 1046 return (EINVAL); 1047 } 1048 if (dstext == NULL) { 1049 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_DST; 1050 return (EINVAL); 1051 } 1052 if (isrcext == NULL && idstext != NULL) { 1053 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_INNER_SRC; 1054 return (EINVAL); 1055 } 1056 if (isrcext != NULL && idstext == NULL) { 1057 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_INNER_DST; 1058 return (EINVAL); 1059 } 1060 if (assoc == NULL) { 1061 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_SA; 1062 return (EINVAL); 1063 } 1064 if (key == NULL) { 1065 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_AKEY; 1066 return (EINVAL); 1067 } 1068 1069 src = (struct sockaddr_in *)(srcext + 1); 1070 dst = (struct sockaddr_in *)(dstext + 1); 1071 1072 /* Sundry ADD-specific reality checks. */ 1073 /* XXX STATS : Logging/stats here? */ 1074 1075 if ((assoc->sadb_sa_state != SADB_SASTATE_MATURE) && 1076 (assoc->sadb_sa_state != SADB_X_SASTATE_ACTIVE_ELSEWHERE)) { 1077 *diagnostic = SADB_X_DIAGNOSTIC_BAD_SASTATE; 1078 return (EINVAL); 1079 } 1080 if (assoc->sadb_sa_encrypt != SADB_EALG_NONE) { 1081 *diagnostic = SADB_X_DIAGNOSTIC_ENCR_NOTSUPP; 1082 return (EINVAL); 1083 } 1084 if (assoc->sadb_sa_flags & ~ahstack->ah_sadb.s_addflags) { 1085 *diagnostic = SADB_X_DIAGNOSTIC_BAD_SAFLAGS; 1086 return (EINVAL); 1087 } 1088 if ((*diagnostic = sadb_hardsoftchk(hard, soft, idle)) != 0) 1089 return (EINVAL); 1090 1091 ASSERT(src->sin_family == dst->sin_family); 1092 1093 /* Stuff I don't support, for now. XXX Diagnostic? */ 1094 if (ksi->ks_in_extv[SADB_EXT_LIFETIME_CURRENT] != NULL) 1095 return (EOPNOTSUPP); 1096 1097 if (ksi->ks_in_extv[SADB_EXT_SENSITIVITY] != NULL) { 1098 if (!is_system_labeled()) 1099 return (EOPNOTSUPP); 1100 } 1101 1102 if (ksi->ks_in_extv[SADB_X_EXT_OUTER_SENS] != NULL) { 1103 if (!is_system_labeled()) 1104 return (EOPNOTSUPP); 1105 } 1106 /* 1107 * XXX Policy : I'm not checking identities at this time, but 1108 * if I did, I'd do them here, before I sent the weak key 1109 * check up to the algorithm. 1110 */ 1111 1112 /* verify that there is a mapping for the specified algorithm */ 1113 rw_enter(&ipss->ipsec_alg_lock, RW_READER); 1114 aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH][assoc->sadb_sa_auth]; 1115 if (aalg == NULL || !ALG_VALID(aalg)) { 1116 rw_exit(&ipss->ipsec_alg_lock); 1117 ah1dbg(ahstack, ("Couldn't find auth alg #%d.\n", 1118 assoc->sadb_sa_auth)); 1119 *diagnostic = SADB_X_DIAGNOSTIC_BAD_AALG; 1120 return (EINVAL); 1121 } 1122 ASSERT(aalg->alg_mech_type != CRYPTO_MECHANISM_INVALID); 1123 1124 /* sanity check key sizes */ 1125 if (!ipsec_valid_key_size(key->sadb_key_bits, aalg)) { 1126 rw_exit(&ipss->ipsec_alg_lock); 1127 *diagnostic = SADB_X_DIAGNOSTIC_BAD_AKEYBITS; 1128 return (EINVAL); 1129 } 1130 1131 /* check key and fix parity if needed */ 1132 if (ipsec_check_key(aalg->alg_mech_type, key, B_TRUE, 1133 diagnostic) != 0) { 1134 rw_exit(&ipss->ipsec_alg_lock); 1135 return (EINVAL); 1136 } 1137 1138 rw_exit(&ipss->ipsec_alg_lock); 1139 1140 return (ah_add_sa_finish(mp, (sadb_msg_t *)mp->b_cont->b_rptr, ksi, 1141 diagnostic, ahstack)); 1142 } 1143 1144 /* Refactor me */ 1145 /* 1146 * Update a security association. Updates come in two varieties. The first 1147 * is an update of lifetimes on a non-larval SA. The second is an update of 1148 * a larval SA, which ends up looking a lot more like an add. 1149 */ 1150 static int 1151 ah_update_sa(mblk_t *mp, keysock_in_t *ksi, int *diagnostic, 1152 ipsecah_stack_t *ahstack, uint8_t sadb_msg_type) 1153 { 1154 sadb_sa_t *assoc = (sadb_sa_t *)ksi->ks_in_extv[SADB_EXT_SA]; 1155 sadb_address_t *dstext = 1156 (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_DST]; 1157 mblk_t *buf_pkt; 1158 int rcode; 1159 1160 if (dstext == NULL) { 1161 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_DST; 1162 return (EINVAL); 1163 } 1164 1165 rcode = sadb_update_sa(mp, ksi, &buf_pkt, &ahstack->ah_sadb, 1166 diagnostic, ahstack->ah_pfkey_q, ah_add_sa, 1167 ahstack->ipsecah_netstack, sadb_msg_type); 1168 1169 if ((assoc->sadb_sa_state != SADB_X_SASTATE_ACTIVE) || 1170 (rcode != 0)) { 1171 return (rcode); 1172 } 1173 1174 HANDLE_BUF_PKT(ah_taskq, ahstack->ipsecah_netstack->netstack_ipsec, 1175 ahstack->ah_dropper, buf_pkt); 1176 1177 return (rcode); 1178 } 1179 1180 /* Refactor me */ 1181 /* 1182 * Delete a security association. This is REALLY likely to be code common to 1183 * both AH and ESP. Find the association, then unlink it. 1184 */ 1185 static int 1186 ah_del_sa(mblk_t *mp, keysock_in_t *ksi, int *diagnostic, 1187 ipsecah_stack_t *ahstack, uint8_t sadb_msg_type) 1188 { 1189 sadb_sa_t *assoc = (sadb_sa_t *)ksi->ks_in_extv[SADB_EXT_SA]; 1190 sadb_address_t *dstext = 1191 (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_DST]; 1192 sadb_address_t *srcext = 1193 (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_SRC]; 1194 struct sockaddr_in *sin; 1195 1196 if (assoc == NULL) { 1197 if (dstext != NULL) 1198 sin = (struct sockaddr_in *)(dstext + 1); 1199 else if (srcext != NULL) 1200 sin = (struct sockaddr_in *)(srcext + 1); 1201 else { 1202 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_SA; 1203 return (EINVAL); 1204 } 1205 return (sadb_purge_sa(mp, ksi, 1206 (sin->sin_family == AF_INET6) ? &ahstack->ah_sadb.s_v6 : 1207 &ahstack->ah_sadb.s_v4, diagnostic, ahstack->ah_pfkey_q)); 1208 } 1209 1210 return (sadb_delget_sa(mp, ksi, &ahstack->ah_sadb, diagnostic, 1211 ahstack->ah_pfkey_q, sadb_msg_type)); 1212 } 1213 1214 /* Refactor me */ 1215 /* 1216 * Convert the entire contents of all of AH's SA tables into PF_KEY SADB_DUMP 1217 * messages. 1218 */ 1219 static void 1220 ah_dump(mblk_t *mp, keysock_in_t *ksi, ipsecah_stack_t *ahstack) 1221 { 1222 int error; 1223 sadb_msg_t *samsg; 1224 1225 /* 1226 * Dump each fanout, bailing if error is non-zero. 1227 */ 1228 1229 error = sadb_dump(ahstack->ah_pfkey_q, mp, ksi, &ahstack->ah_sadb.s_v4); 1230 if (error != 0) 1231 goto bail; 1232 1233 error = sadb_dump(ahstack->ah_pfkey_q, mp, ksi, &ahstack->ah_sadb.s_v6); 1234 bail: 1235 ASSERT(mp->b_cont != NULL); 1236 samsg = (sadb_msg_t *)mp->b_cont->b_rptr; 1237 samsg->sadb_msg_errno = (uint8_t)error; 1238 sadb_pfkey_echo(ahstack->ah_pfkey_q, mp, 1239 (sadb_msg_t *)mp->b_cont->b_rptr, ksi, NULL); 1240 } 1241 1242 /* 1243 * First-cut reality check for an inbound PF_KEY message. 1244 */ 1245 static boolean_t 1246 ah_pfkey_reality_failures(mblk_t *mp, keysock_in_t *ksi, 1247 ipsecah_stack_t *ahstack) 1248 { 1249 int diagnostic; 1250 1251 if (mp->b_cont == NULL) { 1252 freemsg(mp); 1253 return (B_TRUE); 1254 } 1255 1256 if (ksi->ks_in_extv[SADB_EXT_KEY_ENCRYPT] != NULL) { 1257 diagnostic = SADB_X_DIAGNOSTIC_EKEY_PRESENT; 1258 goto badmsg; 1259 } 1260 if (ksi->ks_in_extv[SADB_EXT_PROPOSAL] != NULL) { 1261 diagnostic = SADB_X_DIAGNOSTIC_PROP_PRESENT; 1262 goto badmsg; 1263 } 1264 if (ksi->ks_in_extv[SADB_EXT_SUPPORTED_AUTH] != NULL || 1265 ksi->ks_in_extv[SADB_EXT_SUPPORTED_ENCRYPT] != NULL) { 1266 diagnostic = SADB_X_DIAGNOSTIC_SUPP_PRESENT; 1267 goto badmsg; 1268 } 1269 return (B_FALSE); /* False ==> no failures */ 1270 1271 badmsg: 1272 sadb_pfkey_error(ahstack->ah_pfkey_q, mp, EINVAL, 1273 diagnostic, ksi->ks_in_serial); 1274 return (B_TRUE); /* True ==> failures */ 1275 } 1276 1277 /* 1278 * AH parsing of PF_KEY messages. Keysock did most of the really silly 1279 * error cases. What I receive is a fully-formed, syntactically legal 1280 * PF_KEY message. I then need to check semantics... 1281 * 1282 * This code may become common to AH and ESP. Stay tuned. 1283 * 1284 * I also make the assumption that db_ref's are cool. If this assumption 1285 * is wrong, this means that someone other than keysock or me has been 1286 * mucking with PF_KEY messages. 1287 */ 1288 static void 1289 ah_parse_pfkey(mblk_t *mp, ipsecah_stack_t *ahstack) 1290 { 1291 mblk_t *msg = mp->b_cont; 1292 sadb_msg_t *samsg; 1293 keysock_in_t *ksi; 1294 int error; 1295 int diagnostic = SADB_X_DIAGNOSTIC_NONE; 1296 1297 ASSERT(msg != NULL); 1298 1299 samsg = (sadb_msg_t *)msg->b_rptr; 1300 ksi = (keysock_in_t *)mp->b_rptr; 1301 1302 /* 1303 * If applicable, convert unspecified AF_INET6 to unspecified 1304 * AF_INET. 1305 */ 1306 if (!sadb_addrfix(ksi, ahstack->ah_pfkey_q, mp, 1307 ahstack->ipsecah_netstack) || 1308 ah_pfkey_reality_failures(mp, ksi, ahstack)) { 1309 return; 1310 } 1311 1312 switch (samsg->sadb_msg_type) { 1313 case SADB_ADD: 1314 error = ah_add_sa(mp, ksi, &diagnostic, 1315 ahstack->ipsecah_netstack); 1316 if (error != 0) { 1317 sadb_pfkey_error(ahstack->ah_pfkey_q, mp, error, 1318 diagnostic, ksi->ks_in_serial); 1319 } 1320 /* else ah_add_sa() took care of things. */ 1321 break; 1322 case SADB_DELETE: 1323 case SADB_X_DELPAIR: 1324 case SADB_X_DELPAIR_STATE: 1325 error = ah_del_sa(mp, ksi, &diagnostic, ahstack, 1326 samsg->sadb_msg_type); 1327 if (error != 0) { 1328 sadb_pfkey_error(ahstack->ah_pfkey_q, mp, error, 1329 diagnostic, ksi->ks_in_serial); 1330 } 1331 /* Else ah_del_sa() took care of things. */ 1332 break; 1333 case SADB_GET: 1334 error = sadb_delget_sa(mp, ksi, &ahstack->ah_sadb, &diagnostic, 1335 ahstack->ah_pfkey_q, samsg->sadb_msg_type); 1336 if (error != 0) { 1337 sadb_pfkey_error(ahstack->ah_pfkey_q, mp, error, 1338 diagnostic, ksi->ks_in_serial); 1339 } 1340 /* Else sadb_get_sa() took care of things. */ 1341 break; 1342 case SADB_FLUSH: 1343 sadbp_flush(&ahstack->ah_sadb, ahstack->ipsecah_netstack); 1344 sadb_pfkey_echo(ahstack->ah_pfkey_q, mp, samsg, ksi, NULL); 1345 break; 1346 case SADB_REGISTER: 1347 /* 1348 * Hmmm, let's do it! Check for extensions (there should 1349 * be none), extract the fields, call ah_register_out(), 1350 * then either free or report an error. 1351 * 1352 * Keysock takes care of the PF_KEY bookkeeping for this. 1353 */ 1354 if (ah_register_out(samsg->sadb_msg_seq, samsg->sadb_msg_pid, 1355 ksi->ks_in_serial, ahstack, msg_getcred(mp, NULL))) { 1356 freemsg(mp); 1357 } else { 1358 /* 1359 * Only way this path hits is if there is a memory 1360 * failure. It will not return B_FALSE because of 1361 * lack of ah_pfkey_q if I am in wput(). 1362 */ 1363 sadb_pfkey_error(ahstack->ah_pfkey_q, mp, ENOMEM, 1364 diagnostic, ksi->ks_in_serial); 1365 } 1366 break; 1367 case SADB_UPDATE: 1368 case SADB_X_UPDATEPAIR: 1369 /* 1370 * Find a larval, if not there, find a full one and get 1371 * strict. 1372 */ 1373 error = ah_update_sa(mp, ksi, &diagnostic, ahstack, 1374 samsg->sadb_msg_type); 1375 if (error != 0) { 1376 sadb_pfkey_error(ahstack->ah_pfkey_q, mp, error, 1377 diagnostic, ksi->ks_in_serial); 1378 } 1379 /* else ah_update_sa() took care of things. */ 1380 break; 1381 case SADB_GETSPI: 1382 /* 1383 * Reserve a new larval entry. 1384 */ 1385 ah_getspi(mp, ksi, ahstack); 1386 break; 1387 case SADB_ACQUIRE: 1388 /* 1389 * Find larval and/or ACQUIRE record and kill it (them), I'm 1390 * most likely an error. Inbound ACQUIRE messages should only 1391 * have the base header. 1392 */ 1393 sadb_in_acquire(samsg, &ahstack->ah_sadb, ahstack->ah_pfkey_q, 1394 ahstack->ipsecah_netstack); 1395 freemsg(mp); 1396 break; 1397 case SADB_DUMP: 1398 /* 1399 * Dump all entries. 1400 */ 1401 ah_dump(mp, ksi, ahstack); 1402 /* ah_dump will take care of the return message, etc. */ 1403 break; 1404 case SADB_EXPIRE: 1405 /* Should never reach me. */ 1406 sadb_pfkey_error(ahstack->ah_pfkey_q, mp, EOPNOTSUPP, 1407 diagnostic, ksi->ks_in_serial); 1408 break; 1409 default: 1410 sadb_pfkey_error(ahstack->ah_pfkey_q, mp, EINVAL, 1411 SADB_X_DIAGNOSTIC_UNKNOWN_MSG, ksi->ks_in_serial); 1412 break; 1413 } 1414 } 1415 1416 /* 1417 * Handle case where PF_KEY says it can't find a keysock for one of my 1418 * ACQUIRE messages. 1419 */ 1420 static void 1421 ah_keysock_no_socket(mblk_t *mp, ipsecah_stack_t *ahstack) 1422 { 1423 sadb_msg_t *samsg; 1424 keysock_out_err_t *kse = (keysock_out_err_t *)mp->b_rptr; 1425 1426 if (mp->b_cont == NULL) { 1427 freemsg(mp); 1428 return; 1429 } 1430 samsg = (sadb_msg_t *)mp->b_cont->b_rptr; 1431 1432 /* 1433 * If keysock can't find any registered, delete the acquire record 1434 * immediately, and handle errors. 1435 */ 1436 if (samsg->sadb_msg_type == SADB_ACQUIRE) { 1437 samsg->sadb_msg_errno = kse->ks_err_errno; 1438 samsg->sadb_msg_len = SADB_8TO64(sizeof (*samsg)); 1439 /* 1440 * Use the write-side of the ah_pfkey_q 1441 */ 1442 sadb_in_acquire(samsg, &ahstack->ah_sadb, 1443 WR(ahstack->ah_pfkey_q), ahstack->ipsecah_netstack); 1444 } 1445 1446 freemsg(mp); 1447 } 1448 1449 /* 1450 * AH module read put routine. 1451 */ 1452 static int 1453 ipsecah_rput(queue_t *q, mblk_t *mp) 1454 { 1455 putnext(q, mp); 1456 return (0); 1457 } 1458 1459 /* 1460 * AH module write put routine. 1461 */ 1462 static int 1463 ipsecah_wput(queue_t *q, mblk_t *mp) 1464 { 1465 ipsec_info_t *ii; 1466 struct iocblk *iocp; 1467 ipsecah_stack_t *ahstack = (ipsecah_stack_t *)q->q_ptr; 1468 1469 ah3dbg(ahstack, ("In ah_wput().\n")); 1470 1471 /* NOTE: Each case must take care of freeing or passing mp. */ 1472 switch (mp->b_datap->db_type) { 1473 case M_CTL: 1474 if ((mp->b_wptr - mp->b_rptr) < sizeof (ipsec_info_t)) { 1475 /* Not big enough message. */ 1476 freemsg(mp); 1477 break; 1478 } 1479 ii = (ipsec_info_t *)mp->b_rptr; 1480 1481 switch (ii->ipsec_info_type) { 1482 case KEYSOCK_OUT_ERR: 1483 ah1dbg(ahstack, ("Got KEYSOCK_OUT_ERR message.\n")); 1484 ah_keysock_no_socket(mp, ahstack); 1485 break; 1486 case KEYSOCK_IN: 1487 AH_BUMP_STAT(ahstack, keysock_in); 1488 ah3dbg(ahstack, ("Got KEYSOCK_IN message.\n")); 1489 1490 /* Parse the message. */ 1491 ah_parse_pfkey(mp, ahstack); 1492 break; 1493 case KEYSOCK_HELLO: 1494 sadb_keysock_hello(&ahstack->ah_pfkey_q, q, mp, 1495 ah_ager, (void *)ahstack, &ahstack->ah_event, 1496 SADB_SATYPE_AH); 1497 break; 1498 default: 1499 ah1dbg(ahstack, ("Got M_CTL from above of 0x%x.\n", 1500 ii->ipsec_info_type)); 1501 freemsg(mp); 1502 break; 1503 } 1504 break; 1505 case M_IOCTL: 1506 iocp = (struct iocblk *)mp->b_rptr; 1507 switch (iocp->ioc_cmd) { 1508 case ND_SET: 1509 case ND_GET: 1510 if (nd_getset(q, ahstack->ipsecah_g_nd, mp)) { 1511 qreply(q, mp); 1512 return (0); 1513 } else { 1514 iocp->ioc_error = ENOENT; 1515 } 1516 /* FALLTHRU */ 1517 default: 1518 /* We really don't support any other ioctls, do we? */ 1519 1520 /* Return EINVAL */ 1521 if (iocp->ioc_error != ENOENT) 1522 iocp->ioc_error = EINVAL; 1523 iocp->ioc_count = 0; 1524 mp->b_datap->db_type = M_IOCACK; 1525 qreply(q, mp); 1526 return (0); 1527 } 1528 default: 1529 ah3dbg(ahstack, 1530 ("Got default message, type %d, passing to IP.\n", 1531 mp->b_datap->db_type)); 1532 putnext(q, mp); 1533 } 1534 return (0); 1535 } 1536 1537 /* Refactor me */ 1538 /* 1539 * Updating use times can be tricky business if the ipsa_haspeer flag is 1540 * set. This function is called once in an SA's lifetime. 1541 * 1542 * Caller has to REFRELE "assoc" which is passed in. This function has 1543 * to REFRELE any peer SA that is obtained. 1544 */ 1545 static void 1546 ah_set_usetime(ipsa_t *assoc, boolean_t inbound) 1547 { 1548 ipsa_t *inassoc, *outassoc; 1549 isaf_t *bucket; 1550 sadb_t *sp; 1551 int outhash; 1552 boolean_t isv6; 1553 netstack_t *ns = assoc->ipsa_netstack; 1554 ipsecah_stack_t *ahstack = ns->netstack_ipsecah; 1555 1556 /* No peer? No problem! */ 1557 if (!assoc->ipsa_haspeer) { 1558 sadb_set_usetime(assoc); 1559 return; 1560 } 1561 1562 /* 1563 * Otherwise, we want to grab both the original assoc and its peer. 1564 * There might be a race for this, but if it's a real race, the times 1565 * will be out-of-synch by at most a second, and since our time 1566 * granularity is a second, this won't be a problem. 1567 * 1568 * If we need tight synchronization on the peer SA, then we need to 1569 * reconsider. 1570 */ 1571 1572 /* Use address family to select IPv6/IPv4 */ 1573 isv6 = (assoc->ipsa_addrfam == AF_INET6); 1574 if (isv6) { 1575 sp = &ahstack->ah_sadb.s_v6; 1576 } else { 1577 sp = &ahstack->ah_sadb.s_v4; 1578 ASSERT(assoc->ipsa_addrfam == AF_INET); 1579 } 1580 if (inbound) { 1581 inassoc = assoc; 1582 if (isv6) 1583 outhash = OUTBOUND_HASH_V6(sp, 1584 *((in6_addr_t *)&inassoc->ipsa_dstaddr)); 1585 else 1586 outhash = OUTBOUND_HASH_V4(sp, 1587 *((ipaddr_t *)&inassoc->ipsa_dstaddr)); 1588 bucket = &sp->sdb_of[outhash]; 1589 1590 mutex_enter(&bucket->isaf_lock); 1591 outassoc = ipsec_getassocbyspi(bucket, inassoc->ipsa_spi, 1592 inassoc->ipsa_srcaddr, inassoc->ipsa_dstaddr, 1593 inassoc->ipsa_addrfam); 1594 mutex_exit(&bucket->isaf_lock); 1595 if (outassoc == NULL) { 1596 /* Q: Do we wish to set haspeer == B_FALSE? */ 1597 ah0dbg(("ah_set_usetime: " 1598 "can't find peer for inbound.\n")); 1599 sadb_set_usetime(inassoc); 1600 return; 1601 } 1602 } else { 1603 outassoc = assoc; 1604 bucket = INBOUND_BUCKET(sp, outassoc->ipsa_spi); 1605 mutex_enter(&bucket->isaf_lock); 1606 inassoc = ipsec_getassocbyspi(bucket, outassoc->ipsa_spi, 1607 outassoc->ipsa_srcaddr, outassoc->ipsa_dstaddr, 1608 outassoc->ipsa_addrfam); 1609 mutex_exit(&bucket->isaf_lock); 1610 if (inassoc == NULL) { 1611 /* Q: Do we wish to set haspeer == B_FALSE? */ 1612 ah0dbg(("ah_set_usetime: " 1613 "can't find peer for outbound.\n")); 1614 sadb_set_usetime(outassoc); 1615 return; 1616 } 1617 } 1618 1619 /* Update usetime on both. */ 1620 sadb_set_usetime(inassoc); 1621 sadb_set_usetime(outassoc); 1622 1623 /* 1624 * REFRELE any peer SA. 1625 * 1626 * Because of the multi-line macro nature of IPSA_REFRELE, keep 1627 * them in { }. 1628 */ 1629 if (inbound) { 1630 IPSA_REFRELE(outassoc); 1631 } else { 1632 IPSA_REFRELE(inassoc); 1633 } 1634 } 1635 1636 /* Refactor me */ 1637 /* 1638 * Add a number of bytes to what the SA has protected so far. Return 1639 * B_TRUE if the SA can still protect that many bytes. 1640 * 1641 * Caller must REFRELE the passed-in assoc. This function must REFRELE 1642 * any obtained peer SA. 1643 */ 1644 static boolean_t 1645 ah_age_bytes(ipsa_t *assoc, uint64_t bytes, boolean_t inbound) 1646 { 1647 ipsa_t *inassoc, *outassoc; 1648 isaf_t *bucket; 1649 boolean_t inrc, outrc, isv6; 1650 sadb_t *sp; 1651 int outhash; 1652 netstack_t *ns = assoc->ipsa_netstack; 1653 ipsecah_stack_t *ahstack = ns->netstack_ipsecah; 1654 1655 /* No peer? No problem! */ 1656 if (!assoc->ipsa_haspeer) { 1657 return (sadb_age_bytes(ahstack->ah_pfkey_q, assoc, bytes, 1658 B_TRUE)); 1659 } 1660 1661 /* 1662 * Otherwise, we want to grab both the original assoc and its peer. 1663 * There might be a race for this, but if it's a real race, two 1664 * expire messages may occur. We limit this by only sending the 1665 * expire message on one of the peers, we'll pick the inbound 1666 * arbitrarily. 1667 * 1668 * If we need tight synchronization on the peer SA, then we need to 1669 * reconsider. 1670 */ 1671 1672 /* Pick v4/v6 bucket based on addrfam. */ 1673 isv6 = (assoc->ipsa_addrfam == AF_INET6); 1674 if (isv6) { 1675 sp = &ahstack->ah_sadb.s_v6; 1676 } else { 1677 sp = &ahstack->ah_sadb.s_v4; 1678 ASSERT(assoc->ipsa_addrfam == AF_INET); 1679 } 1680 if (inbound) { 1681 inassoc = assoc; 1682 if (isv6) 1683 outhash = OUTBOUND_HASH_V6(sp, 1684 *((in6_addr_t *)&inassoc->ipsa_dstaddr)); 1685 else 1686 outhash = OUTBOUND_HASH_V4(sp, 1687 *((ipaddr_t *)&inassoc->ipsa_dstaddr)); 1688 bucket = &sp->sdb_of[outhash]; 1689 mutex_enter(&bucket->isaf_lock); 1690 outassoc = ipsec_getassocbyspi(bucket, inassoc->ipsa_spi, 1691 inassoc->ipsa_srcaddr, inassoc->ipsa_dstaddr, 1692 inassoc->ipsa_addrfam); 1693 mutex_exit(&bucket->isaf_lock); 1694 if (outassoc == NULL) { 1695 /* Q: Do we wish to set haspeer == B_FALSE? */ 1696 ah0dbg(("ah_age_bytes: " 1697 "can't find peer for inbound.\n")); 1698 return (sadb_age_bytes(ahstack->ah_pfkey_q, inassoc, 1699 bytes, B_TRUE)); 1700 } 1701 } else { 1702 outassoc = assoc; 1703 bucket = INBOUND_BUCKET(sp, outassoc->ipsa_spi); 1704 mutex_enter(&bucket->isaf_lock); 1705 inassoc = ipsec_getassocbyspi(bucket, outassoc->ipsa_spi, 1706 outassoc->ipsa_srcaddr, outassoc->ipsa_dstaddr, 1707 outassoc->ipsa_addrfam); 1708 mutex_exit(&bucket->isaf_lock); 1709 if (inassoc == NULL) { 1710 /* Q: Do we wish to set haspeer == B_FALSE? */ 1711 ah0dbg(("ah_age_bytes: " 1712 "can't find peer for outbound.\n")); 1713 return (sadb_age_bytes(ahstack->ah_pfkey_q, outassoc, 1714 bytes, B_TRUE)); 1715 } 1716 } 1717 1718 inrc = sadb_age_bytes(ahstack->ah_pfkey_q, inassoc, bytes, B_TRUE); 1719 outrc = sadb_age_bytes(ahstack->ah_pfkey_q, outassoc, bytes, B_FALSE); 1720 1721 /* 1722 * REFRELE any peer SA. 1723 * 1724 * Because of the multi-line macro nature of IPSA_REFRELE, keep 1725 * them in { }. 1726 */ 1727 if (inbound) { 1728 IPSA_REFRELE(outassoc); 1729 } else { 1730 IPSA_REFRELE(inassoc); 1731 } 1732 1733 return (inrc && outrc); 1734 } 1735 1736 /* Refactor me */ 1737 /* 1738 * Handle the SADB_GETSPI message. Create a larval SA. 1739 */ 1740 static void 1741 ah_getspi(mblk_t *mp, keysock_in_t *ksi, ipsecah_stack_t *ahstack) 1742 { 1743 ipsa_t *newbie, *target; 1744 isaf_t *outbound, *inbound; 1745 int rc, diagnostic; 1746 sadb_sa_t *assoc; 1747 keysock_out_t *kso; 1748 uint32_t newspi; 1749 1750 /* 1751 * Randomly generate a proposed SPI value. 1752 */ 1753 if (cl_inet_getspi != NULL) { 1754 cl_inet_getspi(ahstack->ipsecah_netstack->netstack_stackid, 1755 IPPROTO_AH, (uint8_t *)&newspi, sizeof (uint32_t), NULL); 1756 } else { 1757 (void) random_get_pseudo_bytes((uint8_t *)&newspi, 1758 sizeof (uint32_t)); 1759 } 1760 newbie = sadb_getspi(ksi, newspi, &diagnostic, 1761 ahstack->ipsecah_netstack, IPPROTO_AH); 1762 1763 if (newbie == NULL) { 1764 sadb_pfkey_error(ahstack->ah_pfkey_q, mp, ENOMEM, diagnostic, 1765 ksi->ks_in_serial); 1766 return; 1767 } else if (newbie == (ipsa_t *)-1) { 1768 sadb_pfkey_error(ahstack->ah_pfkey_q, mp, EINVAL, diagnostic, 1769 ksi->ks_in_serial); 1770 return; 1771 } 1772 1773 /* 1774 * XXX - We may randomly collide. We really should recover from this. 1775 * Unfortunately, that could require spending way-too-much-time 1776 * in here. For now, let the user retry. 1777 */ 1778 1779 if (newbie->ipsa_addrfam == AF_INET6) { 1780 outbound = OUTBOUND_BUCKET_V6(&ahstack->ah_sadb.s_v6, 1781 *(uint32_t *)(newbie->ipsa_dstaddr)); 1782 inbound = INBOUND_BUCKET(&ahstack->ah_sadb.s_v6, 1783 newbie->ipsa_spi); 1784 } else { 1785 outbound = OUTBOUND_BUCKET_V4(&ahstack->ah_sadb.s_v4, 1786 *(uint32_t *)(newbie->ipsa_dstaddr)); 1787 inbound = INBOUND_BUCKET(&ahstack->ah_sadb.s_v4, 1788 newbie->ipsa_spi); 1789 } 1790 1791 mutex_enter(&outbound->isaf_lock); 1792 mutex_enter(&inbound->isaf_lock); 1793 1794 /* 1795 * Check for collisions (i.e. did sadb_getspi() return with something 1796 * that already exists?). 1797 * 1798 * Try outbound first. Even though SADB_GETSPI is traditionally 1799 * for inbound SAs, you never know what a user might do. 1800 */ 1801 target = ipsec_getassocbyspi(outbound, newbie->ipsa_spi, 1802 newbie->ipsa_srcaddr, newbie->ipsa_dstaddr, newbie->ipsa_addrfam); 1803 if (target == NULL) { 1804 target = ipsec_getassocbyspi(inbound, newbie->ipsa_spi, 1805 newbie->ipsa_srcaddr, newbie->ipsa_dstaddr, 1806 newbie->ipsa_addrfam); 1807 } 1808 1809 /* 1810 * I don't have collisions elsewhere! 1811 * (Nor will I because I'm still holding inbound/outbound locks.) 1812 */ 1813 1814 if (target != NULL) { 1815 rc = EEXIST; 1816 IPSA_REFRELE(target); 1817 } else { 1818 /* 1819 * sadb_insertassoc() also checks for collisions, so 1820 * if there's a colliding larval entry, rc will be set 1821 * to EEXIST. 1822 */ 1823 rc = sadb_insertassoc(newbie, inbound); 1824 newbie->ipsa_hardexpiretime = gethrestime_sec(); 1825 newbie->ipsa_hardexpiretime += ahstack->ipsecah_larval_timeout; 1826 } 1827 1828 /* 1829 * Can exit outbound mutex. Hold inbound until we're done with 1830 * newbie. 1831 */ 1832 mutex_exit(&outbound->isaf_lock); 1833 1834 if (rc != 0) { 1835 mutex_exit(&inbound->isaf_lock); 1836 IPSA_REFRELE(newbie); 1837 sadb_pfkey_error(ahstack->ah_pfkey_q, mp, rc, 1838 SADB_X_DIAGNOSTIC_NONE, ksi->ks_in_serial); 1839 return; 1840 } 1841 1842 /* Can write here because I'm still holding the bucket lock. */ 1843 newbie->ipsa_type = SADB_SATYPE_AH; 1844 1845 /* 1846 * Construct successful return message. We have one thing going 1847 * for us in PF_KEY v2. That's the fact that 1848 * sizeof (sadb_spirange_t) == sizeof (sadb_sa_t) 1849 */ 1850 assoc = (sadb_sa_t *)ksi->ks_in_extv[SADB_EXT_SPIRANGE]; 1851 assoc->sadb_sa_exttype = SADB_EXT_SA; 1852 assoc->sadb_sa_spi = newbie->ipsa_spi; 1853 *((uint64_t *)(&assoc->sadb_sa_replay)) = 0; 1854 mutex_exit(&inbound->isaf_lock); 1855 1856 /* Convert KEYSOCK_IN to KEYSOCK_OUT. */ 1857 kso = (keysock_out_t *)ksi; 1858 kso->ks_out_len = sizeof (*kso); 1859 kso->ks_out_serial = ksi->ks_in_serial; 1860 kso->ks_out_type = KEYSOCK_OUT; 1861 1862 /* 1863 * Can safely putnext() to ah_pfkey_q, because this is a turnaround 1864 * from the ah_pfkey_q. 1865 */ 1866 putnext(ahstack->ah_pfkey_q, mp); 1867 } 1868 1869 /* 1870 * IPv6 sends up the ICMP errors for validation and the removal of the AH 1871 * header. 1872 * If succesful, the mp has been modified to not include the AH header so 1873 * that the caller can fanout to the ULP's icmp error handler. 1874 */ 1875 static mblk_t * 1876 ah_icmp_error_v6(mblk_t *mp, ip_recv_attr_t *ira, ipsecah_stack_t *ahstack) 1877 { 1878 ip6_t *ip6h, *oip6h; 1879 uint16_t hdr_length, ah_length; 1880 uint8_t *nexthdrp; 1881 ah_t *ah; 1882 icmp6_t *icmp6; 1883 isaf_t *isaf; 1884 ipsa_t *assoc; 1885 uint8_t *post_ah_ptr; 1886 ipsec_stack_t *ipss = ahstack->ipsecah_netstack->netstack_ipsec; 1887 1888 /* 1889 * Eat the cost of a pullupmsg() for now. It makes the rest of this 1890 * code far less convoluted. 1891 */ 1892 if (!pullupmsg(mp, -1) || 1893 !ip_hdr_length_nexthdr_v6(mp, (ip6_t *)mp->b_rptr, &hdr_length, 1894 &nexthdrp) || 1895 mp->b_rptr + hdr_length + sizeof (icmp6_t) + sizeof (ip6_t) + 1896 sizeof (ah_t) > mp->b_wptr) { 1897 IP_AH_BUMP_STAT(ipss, in_discards); 1898 ip_drop_packet(mp, B_TRUE, ira->ira_ill, 1899 DROPPER(ipss, ipds_ah_nomem), 1900 &ahstack->ah_dropper); 1901 return (NULL); 1902 } 1903 1904 oip6h = (ip6_t *)mp->b_rptr; 1905 icmp6 = (icmp6_t *)((uint8_t *)oip6h + hdr_length); 1906 ip6h = (ip6_t *)(icmp6 + 1); 1907 if (!ip_hdr_length_nexthdr_v6(mp, ip6h, &hdr_length, &nexthdrp)) { 1908 IP_AH_BUMP_STAT(ipss, in_discards); 1909 ip_drop_packet(mp, B_TRUE, ira->ira_ill, 1910 DROPPER(ipss, ipds_ah_bad_v6_hdrs), 1911 &ahstack->ah_dropper); 1912 return (NULL); 1913 } 1914 ah = (ah_t *)((uint8_t *)ip6h + hdr_length); 1915 1916 isaf = OUTBOUND_BUCKET_V6(&ahstack->ah_sadb.s_v6, ip6h->ip6_dst); 1917 mutex_enter(&isaf->isaf_lock); 1918 assoc = ipsec_getassocbyspi(isaf, ah->ah_spi, 1919 (uint32_t *)&ip6h->ip6_src, (uint32_t *)&ip6h->ip6_dst, AF_INET6); 1920 mutex_exit(&isaf->isaf_lock); 1921 1922 if (assoc == NULL) { 1923 IP_AH_BUMP_STAT(ipss, lookup_failure); 1924 IP_AH_BUMP_STAT(ipss, in_discards); 1925 if (ahstack->ipsecah_log_unknown_spi) { 1926 ipsec_assocfailure(info.mi_idnum, 0, 0, 1927 SL_CONSOLE | SL_WARN | SL_ERROR, 1928 "Bad ICMP message - No association for the " 1929 "attached AH header whose spi is 0x%x, " 1930 "sender is 0x%x\n", 1931 ah->ah_spi, &oip6h->ip6_src, AF_INET6, 1932 ahstack->ipsecah_netstack); 1933 } 1934 ip_drop_packet(mp, B_TRUE, ira->ira_ill, 1935 DROPPER(ipss, ipds_ah_no_sa), 1936 &ahstack->ah_dropper); 1937 return (NULL); 1938 } 1939 1940 IPSA_REFRELE(assoc); 1941 1942 /* 1943 * There seems to be a valid association. If there is enough of AH 1944 * header remove it, otherwise bail. One could check whether it has 1945 * complete AH header plus 8 bytes but it does not make sense if an 1946 * icmp error is returned for ICMP messages e.g ICMP time exceeded, 1947 * that are being sent up. Let the caller figure out. 1948 * 1949 * NOTE: ah_length is the number of 32 bit words minus 2. 1950 */ 1951 ah_length = (ah->ah_length << 2) + 8; 1952 post_ah_ptr = (uint8_t *)ah + ah_length; 1953 1954 if (post_ah_ptr > mp->b_wptr) { 1955 IP_AH_BUMP_STAT(ipss, in_discards); 1956 ip_drop_packet(mp, B_TRUE, ira->ira_ill, 1957 DROPPER(ipss, ipds_ah_bad_length), 1958 &ahstack->ah_dropper); 1959 return (NULL); 1960 } 1961 1962 ip6h->ip6_plen = htons(ntohs(ip6h->ip6_plen) - ah_length); 1963 *nexthdrp = ah->ah_nexthdr; 1964 ovbcopy(post_ah_ptr, ah, 1965 (size_t)((uintptr_t)mp->b_wptr - (uintptr_t)post_ah_ptr)); 1966 mp->b_wptr -= ah_length; 1967 1968 return (mp); 1969 } 1970 1971 /* 1972 * IP sends up the ICMP errors for validation and the removal of 1973 * the AH header. 1974 * If succesful, the mp has been modified to not include the AH header so 1975 * that the caller can fanout to the ULP's icmp error handler. 1976 */ 1977 static mblk_t * 1978 ah_icmp_error_v4(mblk_t *mp, ip_recv_attr_t *ira, ipsecah_stack_t *ahstack) 1979 { 1980 mblk_t *mp1; 1981 icmph_t *icmph; 1982 int iph_hdr_length; 1983 int hdr_length; 1984 isaf_t *hptr; 1985 ipsa_t *assoc; 1986 int ah_length; 1987 ipha_t *ipha; 1988 ipha_t *oipha; 1989 ah_t *ah; 1990 uint32_t length; 1991 int alloc_size; 1992 uint8_t nexthdr; 1993 ipsec_stack_t *ipss = ahstack->ipsecah_netstack->netstack_ipsec; 1994 1995 oipha = ipha = (ipha_t *)mp->b_rptr; 1996 iph_hdr_length = IPH_HDR_LENGTH(ipha); 1997 icmph = (icmph_t *)&mp->b_rptr[iph_hdr_length]; 1998 1999 ipha = (ipha_t *)&icmph[1]; 2000 hdr_length = IPH_HDR_LENGTH(ipha); 2001 2002 /* 2003 * See if we have enough to locate the SPI 2004 */ 2005 if ((uchar_t *)ipha + hdr_length + 8 > mp->b_wptr) { 2006 if (!pullupmsg(mp, (uchar_t *)ipha + hdr_length + 8 - 2007 mp->b_rptr)) { 2008 ipsec_rl_strlog(ahstack->ipsecah_netstack, 2009 info.mi_idnum, 0, 0, 2010 SL_WARN | SL_ERROR, 2011 "ICMP error: Small AH header\n"); 2012 IP_AH_BUMP_STAT(ipss, in_discards); 2013 ip_drop_packet(mp, B_TRUE, ira->ira_ill, 2014 DROPPER(ipss, ipds_ah_bad_length), 2015 &ahstack->ah_dropper); 2016 return (NULL); 2017 } 2018 icmph = (icmph_t *)&mp->b_rptr[iph_hdr_length]; 2019 ipha = (ipha_t *)&icmph[1]; 2020 } 2021 2022 ah = (ah_t *)((uint8_t *)ipha + hdr_length); 2023 nexthdr = ah->ah_nexthdr; 2024 2025 hptr = OUTBOUND_BUCKET_V4(&ahstack->ah_sadb.s_v4, ipha->ipha_dst); 2026 mutex_enter(&hptr->isaf_lock); 2027 assoc = ipsec_getassocbyspi(hptr, ah->ah_spi, 2028 (uint32_t *)&ipha->ipha_src, (uint32_t *)&ipha->ipha_dst, AF_INET); 2029 mutex_exit(&hptr->isaf_lock); 2030 2031 if (assoc == NULL) { 2032 IP_AH_BUMP_STAT(ipss, lookup_failure); 2033 IP_AH_BUMP_STAT(ipss, in_discards); 2034 if (ahstack->ipsecah_log_unknown_spi) { 2035 ipsec_assocfailure(info.mi_idnum, 0, 0, 2036 SL_CONSOLE | SL_WARN | SL_ERROR, 2037 "Bad ICMP message - No association for the " 2038 "attached AH header whose spi is 0x%x, " 2039 "sender is 0x%x\n", 2040 ah->ah_spi, &oipha->ipha_src, AF_INET, 2041 ahstack->ipsecah_netstack); 2042 } 2043 ip_drop_packet(mp, B_TRUE, ira->ira_ill, 2044 DROPPER(ipss, ipds_ah_no_sa), 2045 &ahstack->ah_dropper); 2046 return (NULL); 2047 } 2048 2049 IPSA_REFRELE(assoc); 2050 /* 2051 * There seems to be a valid association. If there 2052 * is enough of AH header remove it, otherwise remove 2053 * as much as possible and send it back. One could check 2054 * whether it has complete AH header plus 8 bytes but it 2055 * does not make sense if an icmp error is returned for 2056 * ICMP messages e.g ICMP time exceeded, that are being 2057 * sent up. Let the caller figure out. 2058 * 2059 * NOTE: ah_length is the number of 32 bit words minus 2. 2060 */ 2061 ah_length = (ah->ah_length << 2) + 8; 2062 2063 if ((uchar_t *)ipha + hdr_length + ah_length > mp->b_wptr) { 2064 if (mp->b_cont == NULL) { 2065 /* 2066 * There is nothing to pullup. Just remove as 2067 * much as possible. This is a common case for 2068 * IPV4. 2069 */ 2070 ah_length = (mp->b_wptr - ((uchar_t *)ipha + 2071 hdr_length)); 2072 goto done; 2073 } 2074 /* Pullup the full ah header */ 2075 if (!pullupmsg(mp, (uchar_t *)ah + ah_length - mp->b_rptr)) { 2076 /* 2077 * pullupmsg could have failed if there was not 2078 * enough to pullup or memory allocation failed. 2079 * We tried hard, give up now. 2080 */ 2081 IP_AH_BUMP_STAT(ipss, in_discards); 2082 ip_drop_packet(mp, B_TRUE, ira->ira_ill, 2083 DROPPER(ipss, ipds_ah_nomem), 2084 &ahstack->ah_dropper); 2085 return (NULL); 2086 } 2087 icmph = (icmph_t *)&mp->b_rptr[iph_hdr_length]; 2088 ipha = (ipha_t *)&icmph[1]; 2089 } 2090 done: 2091 /* 2092 * Remove the AH header and change the protocol. 2093 * Don't update the spi fields in the ip_recv_attr_t 2094 * as we are called just to validate the 2095 * message attached to the ICMP message. 2096 * 2097 * If we never pulled up since all of the message 2098 * is in one single mblk, we can't remove the AH header 2099 * by just setting the b_wptr to the beginning of the 2100 * AH header. We need to allocate a mblk that can hold 2101 * up until the inner IP header and copy them. 2102 */ 2103 alloc_size = iph_hdr_length + sizeof (icmph_t) + hdr_length; 2104 2105 if ((mp1 = allocb(alloc_size, BPRI_LO)) == NULL) { 2106 IP_AH_BUMP_STAT(ipss, in_discards); 2107 ip_drop_packet(mp, B_TRUE, ira->ira_ill, 2108 DROPPER(ipss, ipds_ah_nomem), 2109 &ahstack->ah_dropper); 2110 return (NULL); 2111 } 2112 bcopy(mp->b_rptr, mp1->b_rptr, alloc_size); 2113 mp1->b_wptr += alloc_size; 2114 2115 /* 2116 * Skip whatever we have copied and as much of AH header 2117 * possible. If we still have something left in the original 2118 * message, tag on. 2119 */ 2120 mp->b_rptr = (uchar_t *)ipha + hdr_length + ah_length; 2121 2122 if (mp->b_rptr != mp->b_wptr) { 2123 mp1->b_cont = mp; 2124 } else { 2125 if (mp->b_cont != NULL) 2126 mp1->b_cont = mp->b_cont; 2127 freeb(mp); 2128 } 2129 2130 ipha = (ipha_t *)(mp1->b_rptr + iph_hdr_length + sizeof (icmph_t)); 2131 ipha->ipha_protocol = nexthdr; 2132 length = ntohs(ipha->ipha_length); 2133 length -= ah_length; 2134 ipha->ipha_length = htons((uint16_t)length); 2135 ipha->ipha_hdr_checksum = 0; 2136 ipha->ipha_hdr_checksum = (uint16_t)ip_csum_hdr(ipha); 2137 2138 return (mp1); 2139 } 2140 2141 /* 2142 * IP calls this to validate the ICMP errors that 2143 * we got from the network. 2144 */ 2145 mblk_t * 2146 ipsecah_icmp_error(mblk_t *data_mp, ip_recv_attr_t *ira) 2147 { 2148 netstack_t *ns = ira->ira_ill->ill_ipst->ips_netstack; 2149 ipsecah_stack_t *ahstack = ns->netstack_ipsecah; 2150 2151 if (ira->ira_flags & IRAF_IS_IPV4) 2152 return (ah_icmp_error_v4(data_mp, ira, ahstack)); 2153 else 2154 return (ah_icmp_error_v6(data_mp, ira, ahstack)); 2155 } 2156 2157 static int 2158 ah_fix_tlv_options_v6(uint8_t *oi_opt, uint8_t *pi_opt, uint_t ehdrlen, 2159 uint8_t hdr_type, boolean_t copy_always) 2160 { 2161 uint8_t opt_type; 2162 uint_t optlen; 2163 2164 ASSERT(hdr_type == IPPROTO_DSTOPTS || hdr_type == IPPROTO_HOPOPTS); 2165 2166 /* 2167 * Copy the next header and hdr ext. len of the HOP-by-HOP 2168 * and Destination option. 2169 */ 2170 *pi_opt++ = *oi_opt++; 2171 *pi_opt++ = *oi_opt++; 2172 ehdrlen -= 2; 2173 2174 /* 2175 * Now handle all the TLV encoded options. 2176 */ 2177 while (ehdrlen != 0) { 2178 opt_type = *oi_opt; 2179 2180 if (opt_type == IP6OPT_PAD1) { 2181 optlen = 1; 2182 } else { 2183 if (ehdrlen < 2) 2184 goto bad_opt; 2185 optlen = 2 + oi_opt[1]; 2186 if (optlen > ehdrlen) 2187 goto bad_opt; 2188 } 2189 if (copy_always || !(opt_type & IP6OPT_MUTABLE)) { 2190 bcopy(oi_opt, pi_opt, optlen); 2191 } else { 2192 if (optlen == 1) { 2193 *pi_opt = 0; 2194 } else { 2195 /* 2196 * Copy the type and data length fields. 2197 * Zero the option data by skipping 2198 * option type and option data len 2199 * fields. 2200 */ 2201 *pi_opt = *oi_opt; 2202 *(pi_opt + 1) = *(oi_opt + 1); 2203 bzero(pi_opt + 2, optlen - 2); 2204 } 2205 } 2206 ehdrlen -= optlen; 2207 oi_opt += optlen; 2208 pi_opt += optlen; 2209 } 2210 return (0); 2211 bad_opt: 2212 return (-1); 2213 } 2214 2215 /* 2216 * Construct a pseudo header for AH, processing all the options. 2217 * 2218 * oip6h is the IPv6 header of the incoming or outgoing packet. 2219 * ip6h is the pointer to the pseudo headers IPV6 header. All 2220 * the space needed for the options have been allocated including 2221 * the AH header. 2222 * 2223 * If copy_always is set, all the options that appear before AH are copied 2224 * blindly without checking for IP6OPT_MUTABLE. This is used by 2225 * ah_auth_out_done(). Please refer to that function for details. 2226 * 2227 * NOTE : 2228 * 2229 * * AH header is never copied in this function even if copy_always 2230 * is set. It just returns the ah_offset - offset of the AH header 2231 * and the caller needs to do the copying. This is done so that we 2232 * don't have pass extra arguments e.g. SA etc. and also, 2233 * it is not needed when ah_auth_out_done is calling this function. 2234 */ 2235 static uint_t 2236 ah_fix_phdr_v6(ip6_t *ip6h, ip6_t *oip6h, boolean_t outbound, 2237 boolean_t copy_always) 2238 { 2239 uint8_t *oi_opt; 2240 uint8_t *pi_opt; 2241 uint8_t nexthdr; 2242 uint8_t *prev_nexthdr; 2243 ip6_hbh_t *hbhhdr; 2244 ip6_dest_t *dsthdr = NULL; 2245 ip6_rthdr0_t *rthdr; 2246 int ehdrlen; 2247 ah_t *ah; 2248 int ret; 2249 2250 /* 2251 * In the outbound case for source route, ULP has already moved 2252 * the first hop, which is now in ip6_dst. We need to re-arrange 2253 * the header to make it look like how it would appear in the 2254 * receiver i.e 2255 * 2256 * Because of ip_massage_options_v6 the header looks like 2257 * this : 2258 * 2259 * ip6_src = S, ip6_dst = I1. followed by I2,I3,D. 2260 * 2261 * When it reaches the receiver, it would look like 2262 * 2263 * ip6_src = S, ip6_dst = D. followed by I1,I2,I3. 2264 * 2265 * NOTE : We assume that there are no problems with the options 2266 * as IP should have already checked this. 2267 */ 2268 2269 oi_opt = (uchar_t *)&oip6h[1]; 2270 pi_opt = (uchar_t *)&ip6h[1]; 2271 2272 /* 2273 * We set the prev_nexthdr properly in the pseudo header. 2274 * After we finish authentication and come back from the 2275 * algorithm module, pseudo header will become the real 2276 * IP header. 2277 */ 2278 prev_nexthdr = (uint8_t *)&ip6h->ip6_nxt; 2279 nexthdr = oip6h->ip6_nxt; 2280 /* Assume IP has already stripped it */ 2281 ASSERT(nexthdr != IPPROTO_FRAGMENT); 2282 ah = NULL; 2283 dsthdr = NULL; 2284 for (;;) { 2285 switch (nexthdr) { 2286 case IPPROTO_HOPOPTS: 2287 hbhhdr = (ip6_hbh_t *)oi_opt; 2288 nexthdr = hbhhdr->ip6h_nxt; 2289 ehdrlen = 8 * (hbhhdr->ip6h_len + 1); 2290 ret = ah_fix_tlv_options_v6(oi_opt, pi_opt, ehdrlen, 2291 IPPROTO_HOPOPTS, copy_always); 2292 /* 2293 * Return a zero offset indicating error if there 2294 * was error. 2295 */ 2296 if (ret == -1) 2297 return (0); 2298 hbhhdr = (ip6_hbh_t *)pi_opt; 2299 prev_nexthdr = (uint8_t *)&hbhhdr->ip6h_nxt; 2300 break; 2301 case IPPROTO_ROUTING: 2302 rthdr = (ip6_rthdr0_t *)oi_opt; 2303 nexthdr = rthdr->ip6r0_nxt; 2304 ehdrlen = 8 * (rthdr->ip6r0_len + 1); 2305 if (!copy_always && outbound) { 2306 int i, left; 2307 ip6_rthdr0_t *prthdr; 2308 in6_addr_t *ap, *pap; 2309 2310 left = rthdr->ip6r0_segleft; 2311 prthdr = (ip6_rthdr0_t *)pi_opt; 2312 pap = (in6_addr_t *)(prthdr + 1); 2313 ap = (in6_addr_t *)(rthdr + 1); 2314 /* 2315 * First eight bytes except seg_left 2316 * does not change en route. 2317 */ 2318 bcopy(oi_opt, pi_opt, 8); 2319 prthdr->ip6r0_segleft = 0; 2320 /* 2321 * First address has been moved to 2322 * the destination address of the 2323 * ip header by ip_massage_options_v6. 2324 * And the real destination address is 2325 * in the last address part of the 2326 * option. 2327 */ 2328 *pap = oip6h->ip6_dst; 2329 for (i = 1; i < left - 1; i++) 2330 pap[i] = ap[i - 1]; 2331 ip6h->ip6_dst = *(ap + left - 1); 2332 } else { 2333 bcopy(oi_opt, pi_opt, ehdrlen); 2334 } 2335 rthdr = (ip6_rthdr0_t *)pi_opt; 2336 prev_nexthdr = (uint8_t *)&rthdr->ip6r0_nxt; 2337 break; 2338 case IPPROTO_DSTOPTS: 2339 /* 2340 * Destination options are tricky. If there is 2341 * a terminal (e.g. non-IPv6-extension) header 2342 * following the destination options, don't 2343 * reset prev_nexthdr or advance the AH insertion 2344 * point and just treat this as a terminal header. 2345 * 2346 * If this is an inbound packet, just deal with 2347 * it as is. 2348 */ 2349 dsthdr = (ip6_dest_t *)oi_opt; 2350 /* 2351 * XXX I hope common-subexpression elimination 2352 * saves us the double-evaluate. 2353 */ 2354 if (outbound && dsthdr->ip6d_nxt != IPPROTO_ROUTING && 2355 dsthdr->ip6d_nxt != IPPROTO_HOPOPTS) 2356 goto terminal_hdr; 2357 nexthdr = dsthdr->ip6d_nxt; 2358 ehdrlen = 8 * (dsthdr->ip6d_len + 1); 2359 ret = ah_fix_tlv_options_v6(oi_opt, pi_opt, ehdrlen, 2360 IPPROTO_DSTOPTS, copy_always); 2361 /* 2362 * Return a zero offset indicating error if there 2363 * was error. 2364 */ 2365 if (ret == -1) 2366 return (0); 2367 break; 2368 case IPPROTO_AH: 2369 /* 2370 * Be conservative in what you send. We shouldn't 2371 * see two same-scoped AH's in one packet. 2372 * (Inner-IP-scoped AH will be hit by terminal 2373 * header of IP or IPv6.) 2374 */ 2375 ASSERT(!outbound); 2376 return ((uint_t)(pi_opt - (uint8_t *)ip6h)); 2377 default: 2378 ASSERT(outbound); 2379 terminal_hdr: 2380 *prev_nexthdr = IPPROTO_AH; 2381 ah = (ah_t *)pi_opt; 2382 ah->ah_nexthdr = nexthdr; 2383 return ((uint_t)(pi_opt - (uint8_t *)ip6h)); 2384 } 2385 pi_opt += ehdrlen; 2386 oi_opt += ehdrlen; 2387 } 2388 /* NOTREACHED */ 2389 } 2390 2391 static boolean_t 2392 ah_finish_up(ah_t *phdr_ah, ah_t *inbound_ah, ipsa_t *assoc, 2393 int ah_data_sz, int ah_align_sz, ipsecah_stack_t *ahstack) 2394 { 2395 int i; 2396 2397 /* 2398 * Padding : 2399 * 2400 * 1) Authentication data may have to be padded 2401 * before ICV calculation if ICV is not a multiple 2402 * of 64 bits. This padding is arbitrary and transmitted 2403 * with the packet at the end of the authentication data. 2404 * Payload length should include the padding bytes. 2405 * 2406 * 2) Explicit padding of the whole datagram may be 2407 * required by the algorithm which need not be 2408 * transmitted. It is assumed that this will be taken 2409 * care by the algorithm module. 2410 */ 2411 bzero(phdr_ah + 1, ah_data_sz); /* Zero out ICV for pseudo-hdr. */ 2412 2413 if (inbound_ah == NULL) { 2414 /* Outbound AH datagram. */ 2415 2416 phdr_ah->ah_length = (ah_align_sz >> 2) + 1; 2417 phdr_ah->ah_reserved = 0; 2418 phdr_ah->ah_spi = assoc->ipsa_spi; 2419 2420 phdr_ah->ah_replay = 2421 htonl(atomic_inc_32_nv(&assoc->ipsa_replay)); 2422 if (phdr_ah->ah_replay == 0 && assoc->ipsa_replay_wsize != 0) { 2423 /* 2424 * XXX We have replay counter wrapping. We probably 2425 * want to nuke this SA (and its peer). 2426 */ 2427 ipsec_assocfailure(info.mi_idnum, 0, 0, 2428 SL_ERROR | SL_CONSOLE | SL_WARN, 2429 "Outbound AH SA (0x%x), dst %s has wrapped " 2430 "sequence.\n", phdr_ah->ah_spi, 2431 assoc->ipsa_dstaddr, assoc->ipsa_addrfam, 2432 ahstack->ipsecah_netstack); 2433 2434 sadb_replay_delete(assoc); 2435 /* Caller will free phdr_mp and return NULL. */ 2436 return (B_FALSE); 2437 } 2438 2439 if (ah_data_sz != ah_align_sz) { 2440 uchar_t *pad = ((uchar_t *)phdr_ah + sizeof (ah_t) + 2441 ah_data_sz); 2442 2443 for (i = 0; i < (ah_align_sz - ah_data_sz); i++) { 2444 pad[i] = (uchar_t)i; /* Fill the padding */ 2445 } 2446 } 2447 } else { 2448 /* Inbound AH datagram. */ 2449 phdr_ah->ah_nexthdr = inbound_ah->ah_nexthdr; 2450 phdr_ah->ah_length = inbound_ah->ah_length; 2451 phdr_ah->ah_reserved = 0; 2452 ASSERT(inbound_ah->ah_spi == assoc->ipsa_spi); 2453 phdr_ah->ah_spi = inbound_ah->ah_spi; 2454 phdr_ah->ah_replay = inbound_ah->ah_replay; 2455 2456 if (ah_data_sz != ah_align_sz) { 2457 uchar_t *opad = ((uchar_t *)inbound_ah + 2458 sizeof (ah_t) + ah_data_sz); 2459 uchar_t *pad = ((uchar_t *)phdr_ah + sizeof (ah_t) + 2460 ah_data_sz); 2461 2462 for (i = 0; i < (ah_align_sz - ah_data_sz); i++) { 2463 pad[i] = opad[i]; /* Copy the padding */ 2464 } 2465 } 2466 } 2467 2468 return (B_TRUE); 2469 } 2470 2471 /* 2472 * Called upon failing the inbound ICV check. The message passed as 2473 * argument is freed. 2474 */ 2475 static void 2476 ah_log_bad_auth(mblk_t *mp, ip_recv_attr_t *ira, ipsec_crypto_t *ic) 2477 { 2478 boolean_t isv4 = (ira->ira_flags & IRAF_IS_IPV4); 2479 ipsa_t *assoc = ira->ira_ipsec_ah_sa; 2480 int af; 2481 void *addr; 2482 netstack_t *ns = ira->ira_ill->ill_ipst->ips_netstack; 2483 ipsecah_stack_t *ahstack = ns->netstack_ipsecah; 2484 ipsec_stack_t *ipss = ns->netstack_ipsec; 2485 2486 ASSERT(mp->b_datap->db_type == M_DATA); 2487 2488 mp->b_rptr -= ic->ic_skip_len; 2489 2490 if (isv4) { 2491 ipha_t *ipha = (ipha_t *)mp->b_rptr; 2492 addr = &ipha->ipha_dst; 2493 af = AF_INET; 2494 } else { 2495 ip6_t *ip6h = (ip6_t *)mp->b_rptr; 2496 addr = &ip6h->ip6_dst; 2497 af = AF_INET6; 2498 } 2499 2500 /* 2501 * Log the event. Don't print to the console, block 2502 * potential denial-of-service attack. 2503 */ 2504 AH_BUMP_STAT(ahstack, bad_auth); 2505 2506 ipsec_assocfailure(info.mi_idnum, 0, 0, SL_ERROR | SL_WARN, 2507 "AH Authentication failed spi %x, dst_addr %s", 2508 assoc->ipsa_spi, addr, af, ahstack->ipsecah_netstack); 2509 2510 IP_AH_BUMP_STAT(ipss, in_discards); 2511 ip_drop_packet(mp, B_TRUE, ira->ira_ill, 2512 DROPPER(ipss, ipds_ah_bad_auth), 2513 &ahstack->ah_dropper); 2514 } 2515 2516 /* 2517 * Kernel crypto framework callback invoked after completion of async 2518 * crypto requests for outbound packets. 2519 */ 2520 static void 2521 ah_kcf_callback_outbound(void *arg, int status) 2522 { 2523 mblk_t *mp = (mblk_t *)arg; 2524 mblk_t *async_mp; 2525 netstack_t *ns; 2526 ipsec_stack_t *ipss; 2527 ipsecah_stack_t *ahstack; 2528 mblk_t *data_mp; 2529 ip_xmit_attr_t ixas; 2530 ipsec_crypto_t *ic; 2531 ill_t *ill; 2532 2533 /* 2534 * First remove the ipsec_crypto_t mblk 2535 * Note that we need to ipsec_free_crypto_data(mp) once done with ic. 2536 */ 2537 async_mp = ipsec_remove_crypto_data(mp, &ic); 2538 ASSERT(async_mp != NULL); 2539 2540 /* 2541 * Extract the ip_xmit_attr_t from the first mblk. 2542 * Verifies that the netstack and ill is still around; could 2543 * have vanished while kEf was doing its work. 2544 * On succesful return we have a nce_t and the ill/ipst can't 2545 * disappear until we do the nce_refrele in ixa_cleanup. 2546 */ 2547 data_mp = async_mp->b_cont; 2548 async_mp->b_cont = NULL; 2549 if (!ip_xmit_attr_from_mblk(async_mp, &ixas)) { 2550 /* Disappeared on us - no ill/ipst for MIB */ 2551 if (ixas.ixa_nce != NULL) { 2552 ill = ixas.ixa_nce->nce_ill; 2553 BUMP_MIB(ill->ill_ip_mib, ipIfStatsOutDiscards); 2554 ip_drop_output("ipIfStatsOutDiscards", data_mp, ill); 2555 } 2556 freemsg(data_mp); 2557 goto done; 2558 } 2559 ns = ixas.ixa_ipst->ips_netstack; 2560 ahstack = ns->netstack_ipsecah; 2561 ipss = ns->netstack_ipsec; 2562 ill = ixas.ixa_nce->nce_ill; 2563 2564 if (status == CRYPTO_SUCCESS) { 2565 data_mp = ah_auth_out_done(data_mp, &ixas, ic); 2566 if (data_mp == NULL) 2567 goto done; 2568 2569 (void) ip_output_post_ipsec(data_mp, &ixas); 2570 } else { 2571 /* Outbound shouldn't see invalid MAC */ 2572 ASSERT(status != CRYPTO_INVALID_MAC); 2573 2574 ah1dbg(ahstack, 2575 ("ah_kcf_callback_outbound: crypto failed with 0x%x\n", 2576 status)); 2577 AH_BUMP_STAT(ahstack, crypto_failures); 2578 AH_BUMP_STAT(ahstack, out_discards); 2579 2580 ip_drop_packet(data_mp, B_FALSE, ill, 2581 DROPPER(ipss, ipds_ah_crypto_failed), 2582 &ahstack->ah_dropper); 2583 BUMP_MIB(ill->ill_ip_mib, ipIfStatsOutDiscards); 2584 } 2585 done: 2586 ixa_cleanup(&ixas); 2587 (void) ipsec_free_crypto_data(mp); 2588 } 2589 2590 /* 2591 * Kernel crypto framework callback invoked after completion of async 2592 * crypto requests for inbound packets. 2593 */ 2594 static void 2595 ah_kcf_callback_inbound(void *arg, int status) 2596 { 2597 mblk_t *mp = (mblk_t *)arg; 2598 mblk_t *async_mp; 2599 netstack_t *ns; 2600 ipsec_stack_t *ipss; 2601 ipsecah_stack_t *ahstack; 2602 mblk_t *data_mp; 2603 ip_recv_attr_t iras; 2604 ipsec_crypto_t *ic; 2605 2606 /* 2607 * First remove the ipsec_crypto_t mblk 2608 * Note that we need to ipsec_free_crypto_data(mp) once done with ic. 2609 */ 2610 async_mp = ipsec_remove_crypto_data(mp, &ic); 2611 ASSERT(async_mp != NULL); 2612 2613 /* 2614 * Extract the ip_xmit_attr_t from the first mblk. 2615 * Verifies that the netstack and ill is still around; could 2616 * have vanished while kEf was doing its work. 2617 */ 2618 data_mp = async_mp->b_cont; 2619 async_mp->b_cont = NULL; 2620 if (!ip_recv_attr_from_mblk(async_mp, &iras)) { 2621 /* The ill or ip_stack_t disappeared on us */ 2622 ip_drop_input("ip_recv_attr_from_mblk", data_mp, NULL); 2623 freemsg(data_mp); 2624 goto done; 2625 } 2626 ns = iras.ira_ill->ill_ipst->ips_netstack; 2627 ahstack = ns->netstack_ipsecah; 2628 ipss = ns->netstack_ipsec; 2629 2630 if (status == CRYPTO_SUCCESS) { 2631 data_mp = ah_auth_in_done(data_mp, &iras, ic); 2632 if (data_mp == NULL) 2633 goto done; 2634 2635 /* finish IPsec processing */ 2636 ip_input_post_ipsec(data_mp, &iras); 2637 2638 } else if (status == CRYPTO_INVALID_MAC) { 2639 ah_log_bad_auth(data_mp, &iras, ic); 2640 } else { 2641 ah1dbg(ahstack, 2642 ("ah_kcf_callback_inbound: crypto failed with 0x%x\n", 2643 status)); 2644 AH_BUMP_STAT(ahstack, crypto_failures); 2645 IP_AH_BUMP_STAT(ipss, in_discards); 2646 ip_drop_packet(data_mp, B_TRUE, iras.ira_ill, 2647 DROPPER(ipss, ipds_ah_crypto_failed), 2648 &ahstack->ah_dropper); 2649 BUMP_MIB(iras.ira_ill->ill_ip_mib, ipIfStatsInDiscards); 2650 } 2651 done: 2652 ira_cleanup(&iras, B_TRUE); 2653 (void) ipsec_free_crypto_data(mp); 2654 } 2655 2656 /* 2657 * Invoked on kernel crypto failure during inbound and outbound processing. 2658 */ 2659 static void 2660 ah_crypto_failed(mblk_t *data_mp, boolean_t is_inbound, int kef_rc, 2661 ill_t *ill, ipsecah_stack_t *ahstack) 2662 { 2663 ipsec_stack_t *ipss = ahstack->ipsecah_netstack->netstack_ipsec; 2664 2665 ah1dbg(ahstack, ("crypto failed for %s AH with 0x%x\n", 2666 is_inbound ? "inbound" : "outbound", kef_rc)); 2667 ip_drop_packet(data_mp, is_inbound, ill, 2668 DROPPER(ipss, ipds_ah_crypto_failed), 2669 &ahstack->ah_dropper); 2670 AH_BUMP_STAT(ahstack, crypto_failures); 2671 if (is_inbound) 2672 IP_AH_BUMP_STAT(ipss, in_discards); 2673 else 2674 AH_BUMP_STAT(ahstack, out_discards); 2675 } 2676 2677 /* 2678 * Helper macros for the ah_submit_req_{inbound,outbound}() functions. 2679 */ 2680 2681 /* 2682 * A statement-equivalent macro, _cr MUST point to a modifiable 2683 * crypto_call_req_t. 2684 */ 2685 #define AH_INIT_CALLREQ(_cr, _mp, _callback) \ 2686 (_cr)->cr_flag = CRYPTO_SKIP_REQID|CRYPTO_ALWAYS_QUEUE; \ 2687 (_cr)->cr_callback_arg = (_mp); \ 2688 (_cr)->cr_callback_func = (_callback) 2689 2690 #define AH_INIT_CRYPTO_DATA(data, msglen, mblk) { \ 2691 (data)->cd_format = CRYPTO_DATA_MBLK; \ 2692 (data)->cd_mp = mblk; \ 2693 (data)->cd_offset = 0; \ 2694 (data)->cd_length = msglen; \ 2695 } 2696 2697 #define AH_INIT_CRYPTO_MAC(mac, icvlen, icvbuf) { \ 2698 (mac)->cd_format = CRYPTO_DATA_RAW; \ 2699 (mac)->cd_offset = 0; \ 2700 (mac)->cd_length = icvlen; \ 2701 (mac)->cd_raw.iov_base = icvbuf; \ 2702 (mac)->cd_raw.iov_len = icvlen; \ 2703 } 2704 2705 /* 2706 * Submit an inbound packet for processing by the crypto framework. 2707 */ 2708 static mblk_t * 2709 ah_submit_req_inbound(mblk_t *phdr_mp, ip_recv_attr_t *ira, 2710 size_t skip_len, uint32_t ah_offset, ipsa_t *assoc) 2711 { 2712 int kef_rc; 2713 mblk_t *mp; 2714 crypto_call_req_t call_req, *callrp; 2715 uint_t icv_len = assoc->ipsa_mac_len; 2716 crypto_ctx_template_t ctx_tmpl; 2717 ipsecah_stack_t *ahstack; 2718 ipsec_crypto_t *ic, icstack; 2719 boolean_t force = (assoc->ipsa_flags & IPSA_F_ASYNC); 2720 2721 ahstack = ira->ira_ill->ill_ipst->ips_netstack->netstack_ipsecah; 2722 2723 ASSERT(phdr_mp != NULL); 2724 ASSERT(phdr_mp->b_datap->db_type == M_DATA); 2725 2726 if (force) { 2727 /* We are doing asynch; allocate mblks to hold state */ 2728 if ((mp = ip_recv_attr_to_mblk(ira)) == NULL || 2729 (mp = ipsec_add_crypto_data(mp, &ic)) == NULL) { 2730 BUMP_MIB(ira->ira_ill->ill_ip_mib, ipIfStatsInDiscards); 2731 ip_drop_input("ipIfStatsInDiscards", phdr_mp, 2732 ira->ira_ill); 2733 freemsg(phdr_mp); 2734 return (NULL); 2735 } 2736 2737 linkb(mp, phdr_mp); 2738 callrp = &call_req; 2739 AH_INIT_CALLREQ(callrp, mp, ah_kcf_callback_inbound); 2740 } else { 2741 /* 2742 * If we know we are going to do sync then ipsec_crypto_t 2743 * should be on the stack. 2744 */ 2745 ic = &icstack; 2746 bzero(ic, sizeof (*ic)); 2747 callrp = NULL; 2748 } 2749 2750 /* init arguments for the crypto framework */ 2751 AH_INIT_CRYPTO_DATA(&ic->ic_crypto_data, AH_MSGSIZE(phdr_mp), 2752 phdr_mp); 2753 2754 AH_INIT_CRYPTO_MAC(&ic->ic_crypto_mac, icv_len, 2755 (char *)phdr_mp->b_cont->b_rptr - skip_len + ah_offset + 2756 sizeof (ah_t)); 2757 2758 ic->ic_skip_len = skip_len; 2759 2760 IPSEC_CTX_TMPL(assoc, ipsa_authtmpl, IPSEC_ALG_AUTH, ctx_tmpl); 2761 2762 /* call KEF to do the MAC operation */ 2763 kef_rc = crypto_mac_verify(&assoc->ipsa_amech, 2764 &ic->ic_crypto_data, &assoc->ipsa_kcfauthkey, ctx_tmpl, 2765 &ic->ic_crypto_mac, callrp); 2766 2767 switch (kef_rc) { 2768 case CRYPTO_SUCCESS: 2769 AH_BUMP_STAT(ahstack, crypto_sync); 2770 phdr_mp = ah_auth_in_done(phdr_mp, ira, ic); 2771 if (force) { 2772 /* Free mp after we are done with ic */ 2773 mp = ipsec_free_crypto_data(mp); 2774 (void) ip_recv_attr_free_mblk(mp); 2775 } 2776 return (phdr_mp); 2777 case CRYPTO_QUEUED: 2778 /* ah_kcf_callback_inbound() will be invoked on completion */ 2779 AH_BUMP_STAT(ahstack, crypto_async); 2780 return (NULL); 2781 case CRYPTO_INVALID_MAC: 2782 /* Free mp after we are done with ic */ 2783 AH_BUMP_STAT(ahstack, crypto_sync); 2784 BUMP_MIB(ira->ira_ill->ill_ip_mib, ipIfStatsInDiscards); 2785 ah_log_bad_auth(phdr_mp, ira, ic); 2786 /* phdr_mp was passed to ip_drop_packet */ 2787 if (force) { 2788 mp = ipsec_free_crypto_data(mp); 2789 (void) ip_recv_attr_free_mblk(mp); 2790 } 2791 return (NULL); 2792 } 2793 2794 if (force) { 2795 mp = ipsec_free_crypto_data(mp); 2796 phdr_mp = ip_recv_attr_free_mblk(mp); 2797 } 2798 BUMP_MIB(ira->ira_ill->ill_ip_mib, ipIfStatsInDiscards); 2799 ah_crypto_failed(phdr_mp, B_TRUE, kef_rc, ira->ira_ill, ahstack); 2800 /* phdr_mp was passed to ip_drop_packet */ 2801 return (NULL); 2802 } 2803 2804 /* 2805 * Submit an outbound packet for processing by the crypto framework. 2806 */ 2807 static mblk_t * 2808 ah_submit_req_outbound(mblk_t *phdr_mp, ip_xmit_attr_t *ixa, 2809 size_t skip_len, ipsa_t *assoc) 2810 { 2811 int kef_rc; 2812 mblk_t *mp; 2813 crypto_call_req_t call_req, *callrp; 2814 uint_t icv_len = assoc->ipsa_mac_len; 2815 ipsecah_stack_t *ahstack; 2816 ipsec_crypto_t *ic, icstack; 2817 ill_t *ill = ixa->ixa_nce->nce_ill; 2818 boolean_t force = (assoc->ipsa_flags & IPSA_F_ASYNC); 2819 2820 ahstack = ill->ill_ipst->ips_netstack->netstack_ipsecah; 2821 2822 ASSERT(phdr_mp != NULL); 2823 ASSERT(phdr_mp->b_datap->db_type == M_DATA); 2824 2825 if (force) { 2826 /* We are doing asynch; allocate mblks to hold state */ 2827 if ((mp = ip_xmit_attr_to_mblk(ixa)) == NULL || 2828 (mp = ipsec_add_crypto_data(mp, &ic)) == NULL) { 2829 BUMP_MIB(ill->ill_ip_mib, ipIfStatsOutDiscards); 2830 ip_drop_output("ipIfStatsOutDiscards", phdr_mp, ill); 2831 freemsg(phdr_mp); 2832 return (NULL); 2833 } 2834 linkb(mp, phdr_mp); 2835 callrp = &call_req; 2836 AH_INIT_CALLREQ(callrp, mp, ah_kcf_callback_outbound); 2837 } else { 2838 /* 2839 * If we know we are going to do sync then ipsec_crypto_t 2840 * should be on the stack. 2841 */ 2842 ic = &icstack; 2843 bzero(ic, sizeof (*ic)); 2844 callrp = NULL; 2845 } 2846 2847 /* init arguments for the crypto framework */ 2848 AH_INIT_CRYPTO_DATA(&ic->ic_crypto_data, AH_MSGSIZE(phdr_mp), 2849 phdr_mp); 2850 2851 AH_INIT_CRYPTO_MAC(&ic->ic_crypto_mac, icv_len, 2852 (char *)phdr_mp->b_wptr); 2853 2854 ic->ic_skip_len = skip_len; 2855 2856 ASSERT(ixa->ixa_ipsec_ah_sa != NULL); 2857 2858 /* call KEF to do the MAC operation */ 2859 kef_rc = crypto_mac(&assoc->ipsa_amech, &ic->ic_crypto_data, 2860 &assoc->ipsa_kcfauthkey, assoc->ipsa_authtmpl, 2861 &ic->ic_crypto_mac, callrp); 2862 2863 switch (kef_rc) { 2864 case CRYPTO_SUCCESS: 2865 AH_BUMP_STAT(ahstack, crypto_sync); 2866 phdr_mp = ah_auth_out_done(phdr_mp, ixa, ic); 2867 if (force) { 2868 /* Free mp after we are done with ic */ 2869 mp = ipsec_free_crypto_data(mp); 2870 (void) ip_xmit_attr_free_mblk(mp); 2871 } 2872 return (phdr_mp); 2873 case CRYPTO_QUEUED: 2874 /* ah_kcf_callback_outbound() will be invoked on completion */ 2875 AH_BUMP_STAT(ahstack, crypto_async); 2876 return (NULL); 2877 } 2878 2879 if (force) { 2880 mp = ipsec_free_crypto_data(mp); 2881 phdr_mp = ip_xmit_attr_free_mblk(mp); 2882 } 2883 BUMP_MIB(ill->ill_ip_mib, ipIfStatsOutDiscards); 2884 ah_crypto_failed(phdr_mp, B_FALSE, kef_rc, NULL, ahstack); 2885 /* phdr_mp was passed to ip_drop_packet */ 2886 return (NULL); 2887 } 2888 2889 /* 2890 * This function constructs a pseudo header by looking at the IP header 2891 * and options if any. This is called for both outbound and inbound, 2892 * before computing the ICV. 2893 */ 2894 static mblk_t * 2895 ah_process_ip_options_v6(mblk_t *mp, ipsa_t *assoc, int *length_to_skip, 2896 uint_t ah_data_sz, boolean_t outbound, ipsecah_stack_t *ahstack) 2897 { 2898 ip6_t *ip6h; 2899 ip6_t *oip6h; 2900 mblk_t *phdr_mp; 2901 int option_length; 2902 uint_t ah_align_sz; 2903 uint_t ah_offset; 2904 int hdr_size; 2905 2906 /* 2907 * Allocate space for the authentication data also. It is 2908 * useful both during the ICV calculation where we need to 2909 * feed in zeroes and while sending the datagram back to IP 2910 * where we will be using the same space. 2911 * 2912 * We need to allocate space for padding bytes if it is not 2913 * a multiple of IPV6_PADDING_ALIGN. 2914 * 2915 * In addition, we allocate space for the ICV computed by 2916 * the kernel crypto framework, saving us a separate kmem 2917 * allocation down the road. 2918 */ 2919 2920 ah_align_sz = P2ALIGN(ah_data_sz + IPV6_PADDING_ALIGN - 1, 2921 IPV6_PADDING_ALIGN); 2922 2923 ASSERT(ah_align_sz >= ah_data_sz); 2924 2925 hdr_size = ipsec_ah_get_hdr_size_v6(mp, B_FALSE); 2926 option_length = hdr_size - IPV6_HDR_LEN; 2927 2928 /* This was not included in ipsec_ah_get_hdr_size_v6() */ 2929 hdr_size += (sizeof (ah_t) + ah_align_sz); 2930 2931 if (!outbound && (MBLKL(mp) < hdr_size)) { 2932 /* 2933 * We have post-AH header options in a separate mblk, 2934 * a pullup is required. 2935 */ 2936 if (!pullupmsg(mp, hdr_size)) 2937 return (NULL); 2938 } 2939 2940 if ((phdr_mp = allocb_tmpl(hdr_size + ah_data_sz, mp)) == NULL) { 2941 return (NULL); 2942 } 2943 2944 oip6h = (ip6_t *)mp->b_rptr; 2945 2946 /* 2947 * Form the basic IP header first. Zero out the header 2948 * so that the mutable fields are zeroed out. 2949 */ 2950 ip6h = (ip6_t *)phdr_mp->b_rptr; 2951 bzero(ip6h, sizeof (ip6_t)); 2952 ip6h->ip6_vcf = IPV6_DEFAULT_VERS_AND_FLOW; 2953 2954 if (outbound) { 2955 /* 2956 * Include the size of AH and authentication data. 2957 * This is how our recipient would compute the 2958 * authentication data. Look at what we do in the 2959 * inbound case below. 2960 */ 2961 ip6h->ip6_plen = htons(ntohs(oip6h->ip6_plen) + 2962 sizeof (ah_t) + ah_align_sz); 2963 } else { 2964 ip6h->ip6_plen = oip6h->ip6_plen; 2965 } 2966 2967 ip6h->ip6_src = oip6h->ip6_src; 2968 ip6h->ip6_dst = oip6h->ip6_dst; 2969 2970 *length_to_skip = IPV6_HDR_LEN; 2971 if (option_length == 0) { 2972 /* Form the AH header */ 2973 ip6h->ip6_nxt = IPPROTO_AH; 2974 ((ah_t *)(ip6h + 1))->ah_nexthdr = oip6h->ip6_nxt; 2975 ah_offset = *length_to_skip; 2976 } else { 2977 ip6h->ip6_nxt = oip6h->ip6_nxt; 2978 /* option_length does not include the AH header's size */ 2979 *length_to_skip += option_length; 2980 2981 ah_offset = ah_fix_phdr_v6(ip6h, oip6h, outbound, B_FALSE); 2982 if (ah_offset == 0) { 2983 return (NULL); 2984 } 2985 } 2986 2987 if (!ah_finish_up(((ah_t *)((uint8_t *)ip6h + ah_offset)), 2988 (outbound ? NULL : ((ah_t *)((uint8_t *)oip6h + ah_offset))), 2989 assoc, ah_data_sz, ah_align_sz, ahstack)) { 2990 freeb(phdr_mp); 2991 /* 2992 * Returning NULL will tell the caller to 2993 * IPSA_REFELE(), free the memory, etc. 2994 */ 2995 return (NULL); 2996 } 2997 2998 phdr_mp->b_wptr = ((uint8_t *)ip6h + ah_offset + sizeof (ah_t) + 2999 ah_align_sz); 3000 if (!outbound) 3001 *length_to_skip += sizeof (ah_t) + ah_align_sz; 3002 return (phdr_mp); 3003 } 3004 3005 /* 3006 * This function constructs a pseudo header by looking at the IP header 3007 * and options if any. This is called for both outbound and inbound, 3008 * before computing the ICV. 3009 */ 3010 static mblk_t * 3011 ah_process_ip_options_v4(mblk_t *mp, ipsa_t *assoc, int *length_to_skip, 3012 uint_t ah_data_sz, boolean_t outbound, ipsecah_stack_t *ahstack) 3013 { 3014 ipoptp_t opts; 3015 uint32_t option_length; 3016 ipha_t *ipha; 3017 ipha_t *oipha; 3018 mblk_t *phdr_mp; 3019 int size; 3020 uchar_t *optptr; 3021 uint8_t optval; 3022 uint8_t optlen; 3023 ipaddr_t dst; 3024 uint32_t v_hlen_tos_len; 3025 int ip_hdr_length; 3026 uint_t ah_align_sz; 3027 uint32_t off; 3028 3029 #ifdef _BIG_ENDIAN 3030 #define V_HLEN (v_hlen_tos_len >> 24) 3031 #else 3032 #define V_HLEN (v_hlen_tos_len & 0xFF) 3033 #endif 3034 3035 oipha = (ipha_t *)mp->b_rptr; 3036 v_hlen_tos_len = ((uint32_t *)oipha)[0]; 3037 3038 /* 3039 * Allocate space for the authentication data also. It is 3040 * useful both during the ICV calculation where we need to 3041 * feed in zeroes and while sending the datagram back to IP 3042 * where we will be using the same space. 3043 * 3044 * We need to allocate space for padding bytes if it is not 3045 * a multiple of IPV4_PADDING_ALIGN. 3046 * 3047 * In addition, we allocate space for the ICV computed by 3048 * the kernel crypto framework, saving us a separate kmem 3049 * allocation down the road. 3050 */ 3051 3052 ah_align_sz = P2ALIGN(ah_data_sz + IPV4_PADDING_ALIGN - 1, 3053 IPV4_PADDING_ALIGN); 3054 3055 ASSERT(ah_align_sz >= ah_data_sz); 3056 3057 size = IP_SIMPLE_HDR_LENGTH + sizeof (ah_t) + ah_align_sz + 3058 ah_data_sz; 3059 3060 if (V_HLEN != IP_SIMPLE_HDR_VERSION) { 3061 option_length = oipha->ipha_version_and_hdr_length - 3062 (uint8_t)((IP_VERSION << 4) + 3063 IP_SIMPLE_HDR_LENGTH_IN_WORDS); 3064 option_length <<= 2; 3065 size += option_length; 3066 } 3067 3068 if ((phdr_mp = allocb_tmpl(size, mp)) == NULL) { 3069 return (NULL); 3070 } 3071 3072 /* 3073 * Form the basic IP header first. 3074 */ 3075 ipha = (ipha_t *)phdr_mp->b_rptr; 3076 ipha->ipha_version_and_hdr_length = oipha->ipha_version_and_hdr_length; 3077 ipha->ipha_type_of_service = 0; 3078 3079 if (outbound) { 3080 /* 3081 * Include the size of AH and authentication data. 3082 * This is how our recipient would compute the 3083 * authentication data. Look at what we do in the 3084 * inbound case below. 3085 */ 3086 ipha->ipha_length = ntohs(htons(oipha->ipha_length) + 3087 sizeof (ah_t) + ah_align_sz); 3088 } else { 3089 ipha->ipha_length = oipha->ipha_length; 3090 } 3091 3092 ipha->ipha_ident = oipha->ipha_ident; 3093 ipha->ipha_fragment_offset_and_flags = 0; 3094 ipha->ipha_ttl = 0; 3095 ipha->ipha_protocol = IPPROTO_AH; 3096 ipha->ipha_hdr_checksum = 0; 3097 ipha->ipha_src = oipha->ipha_src; 3098 ipha->ipha_dst = dst = oipha->ipha_dst; 3099 3100 /* 3101 * If there is no option to process return now. 3102 */ 3103 ip_hdr_length = IP_SIMPLE_HDR_LENGTH; 3104 3105 if (V_HLEN == IP_SIMPLE_HDR_VERSION) { 3106 /* Form the AH header */ 3107 goto ah_hdr; 3108 } 3109 3110 ip_hdr_length += option_length; 3111 3112 /* 3113 * We have options. In the outbound case for source route, 3114 * ULP has already moved the first hop, which is now in 3115 * ipha_dst. We need the final destination for the calculation 3116 * of authentication data. And also make sure that mutable 3117 * and experimental fields are zeroed out in the IP options. 3118 */ 3119 3120 bcopy(&oipha[1], &ipha[1], option_length); 3121 3122 for (optval = ipoptp_first(&opts, ipha); 3123 optval != IPOPT_EOL; 3124 optval = ipoptp_next(&opts)) { 3125 optptr = opts.ipoptp_cur; 3126 optlen = opts.ipoptp_len; 3127 switch (optval) { 3128 case IPOPT_EXTSEC: 3129 case IPOPT_COMSEC: 3130 case IPOPT_RA: 3131 case IPOPT_SDMDD: 3132 case IPOPT_SECURITY: 3133 /* 3134 * These options are Immutable, leave them as-is. 3135 * Note that IPOPT_NOP is also Immutable, but it 3136 * was skipped by ipoptp_next() and thus remains 3137 * intact in the header. 3138 */ 3139 break; 3140 case IPOPT_SSRR: 3141 case IPOPT_LSRR: 3142 if ((opts.ipoptp_flags & IPOPTP_ERROR) != 0) 3143 goto bad_ipv4opt; 3144 /* 3145 * These two are mutable and will be zeroed, but 3146 * first get the final destination. 3147 */ 3148 off = optptr[IPOPT_OFFSET]; 3149 /* 3150 * If one of the conditions is true, it means 3151 * end of options and dst already has the right 3152 * value. So, just fall through. 3153 */ 3154 if (!(optlen < IP_ADDR_LEN || off > optlen - 3)) { 3155 off = optlen - IP_ADDR_LEN; 3156 bcopy(&optptr[off], &dst, IP_ADDR_LEN); 3157 } 3158 /* FALLTHRU */ 3159 case IPOPT_RR: 3160 case IPOPT_TS: 3161 case IPOPT_SATID: 3162 default: 3163 /* 3164 * optlen should include from the beginning of an 3165 * option. 3166 * NOTE : Stream Identifier Option (SID): RFC 791 3167 * shows the bit pattern of optlen as 2 and documents 3168 * the length as 4. We assume it to be 2 here. 3169 */ 3170 bzero(optptr, optlen); 3171 break; 3172 } 3173 } 3174 3175 if ((opts.ipoptp_flags & IPOPTP_ERROR) != 0) { 3176 bad_ipv4opt: 3177 ah1dbg(ahstack, ("AH : bad IPv4 option")); 3178 freeb(phdr_mp); 3179 return (NULL); 3180 } 3181 3182 /* 3183 * Don't change ipha_dst for an inbound datagram as it points 3184 * to the right value. Only for the outbound with LSRR/SSRR, 3185 * because of ip_massage_options called by the ULP, ipha_dst 3186 * points to the first hop and we need to use the final 3187 * destination for computing the ICV. 3188 */ 3189 3190 if (outbound) 3191 ipha->ipha_dst = dst; 3192 ah_hdr: 3193 ((ah_t *)((uint8_t *)ipha + ip_hdr_length))->ah_nexthdr = 3194 oipha->ipha_protocol; 3195 if (!ah_finish_up(((ah_t *)((uint8_t *)ipha + ip_hdr_length)), 3196 (outbound ? NULL : ((ah_t *)((uint8_t *)oipha + ip_hdr_length))), 3197 assoc, ah_data_sz, ah_align_sz, ahstack)) { 3198 freeb(phdr_mp); 3199 /* 3200 * Returning NULL will tell the caller to IPSA_REFELE(), free 3201 * the memory, etc. 3202 */ 3203 return (NULL); 3204 } 3205 3206 phdr_mp->b_wptr = ((uchar_t *)ipha + ip_hdr_length + 3207 sizeof (ah_t) + ah_align_sz); 3208 3209 ASSERT(phdr_mp->b_wptr <= phdr_mp->b_datap->db_lim); 3210 if (outbound) 3211 *length_to_skip = ip_hdr_length; 3212 else 3213 *length_to_skip = ip_hdr_length + sizeof (ah_t) + ah_align_sz; 3214 return (phdr_mp); 3215 } 3216 3217 /* 3218 * Authenticate an outbound datagram. This function is called 3219 * whenever IP sends an outbound datagram that needs authentication. 3220 * Returns a modified packet if done. Returns NULL if error or queued. 3221 * If error return then ipIfStatsOutDiscards has been increased. 3222 */ 3223 static mblk_t * 3224 ah_outbound(mblk_t *data_mp, ip_xmit_attr_t *ixa) 3225 { 3226 mblk_t *phdr_mp; 3227 ipsa_t *assoc; 3228 int length_to_skip; 3229 uint_t ah_align_sz; 3230 uint_t age_bytes; 3231 netstack_t *ns = ixa->ixa_ipst->ips_netstack; 3232 ipsecah_stack_t *ahstack = ns->netstack_ipsecah; 3233 ipsec_stack_t *ipss = ns->netstack_ipsec; 3234 ill_t *ill = ixa->ixa_nce->nce_ill; 3235 boolean_t need_refrele = B_FALSE; 3236 3237 /* 3238 * Construct the chain of mblks 3239 * 3240 * PSEUDO_HDR->DATA 3241 * 3242 * one by one. 3243 */ 3244 3245 AH_BUMP_STAT(ahstack, out_requests); 3246 3247 ASSERT(data_mp->b_datap->db_type == M_DATA); 3248 3249 assoc = ixa->ixa_ipsec_ah_sa; 3250 ASSERT(assoc != NULL); 3251 3252 3253 /* 3254 * Get the outer IP header in shape to escape this system.. 3255 */ 3256 if (is_system_labeled() && (assoc->ipsa_otsl != NULL)) { 3257 /* 3258 * Need to update packet with any CIPSO option and update 3259 * ixa_tsl to capture the new label. 3260 * We allocate a separate ixa for that purpose. 3261 */ 3262 ixa = ip_xmit_attr_duplicate(ixa); 3263 if (ixa == NULL) { 3264 ip_drop_packet(data_mp, B_FALSE, ill, 3265 DROPPER(ipss, ipds_ah_nomem), 3266 &ahstack->ah_dropper); 3267 return (NULL); 3268 } 3269 need_refrele = B_TRUE; 3270 3271 label_hold(assoc->ipsa_otsl); 3272 ip_xmit_attr_replace_tsl(ixa, assoc->ipsa_otsl); 3273 3274 data_mp = sadb_whack_label(data_mp, assoc, ixa, 3275 DROPPER(ipss, ipds_ah_nomem), &ahstack->ah_dropper); 3276 if (data_mp == NULL) { 3277 /* Packet dropped by sadb_whack_label */ 3278 ixa_refrele(ixa); 3279 return (NULL); 3280 } 3281 } 3282 3283 /* 3284 * Age SA according to number of bytes that will be sent after 3285 * adding the AH header, ICV, and padding to the packet. 3286 */ 3287 3288 if (ixa->ixa_flags & IXAF_IS_IPV4) { 3289 ipha_t *ipha = (ipha_t *)data_mp->b_rptr; 3290 ah_align_sz = P2ALIGN(assoc->ipsa_mac_len + 3291 IPV4_PADDING_ALIGN - 1, IPV4_PADDING_ALIGN); 3292 age_bytes = ntohs(ipha->ipha_length) + sizeof (ah_t) + 3293 ah_align_sz; 3294 } else { 3295 ip6_t *ip6h = (ip6_t *)data_mp->b_rptr; 3296 ah_align_sz = P2ALIGN(assoc->ipsa_mac_len + 3297 IPV6_PADDING_ALIGN - 1, IPV6_PADDING_ALIGN); 3298 age_bytes = sizeof (ip6_t) + ntohs(ip6h->ip6_plen) + 3299 sizeof (ah_t) + ah_align_sz; 3300 } 3301 3302 if (!ah_age_bytes(assoc, age_bytes, B_FALSE)) { 3303 /* rig things as if ipsec_getassocbyconn() failed */ 3304 ipsec_assocfailure(info.mi_idnum, 0, 0, SL_ERROR | SL_WARN, 3305 "AH association 0x%x, dst %s had bytes expire.\n", 3306 ntohl(assoc->ipsa_spi), assoc->ipsa_dstaddr, AF_INET, 3307 ahstack->ipsecah_netstack); 3308 BUMP_MIB(ill->ill_ip_mib, ipIfStatsOutDiscards); 3309 ip_drop_output("ipIfStatsOutDiscards", data_mp, ill); 3310 freemsg(data_mp); 3311 if (need_refrele) 3312 ixa_refrele(ixa); 3313 return (NULL); 3314 } 3315 3316 /* 3317 * XXX We need to have fixed up the outer label before we get here. 3318 * (AH is computing the checksum over the outer label). 3319 */ 3320 3321 /* 3322 * Insert pseudo header: 3323 * [IP, ULP] => [IP, AH, ICV] -> ULP 3324 */ 3325 3326 if (ixa->ixa_flags & IXAF_IS_IPV4) { 3327 phdr_mp = ah_process_ip_options_v4(data_mp, assoc, 3328 &length_to_skip, assoc->ipsa_mac_len, B_TRUE, ahstack); 3329 } else { 3330 phdr_mp = ah_process_ip_options_v6(data_mp, assoc, 3331 &length_to_skip, assoc->ipsa_mac_len, B_TRUE, ahstack); 3332 } 3333 3334 if (phdr_mp == NULL) { 3335 AH_BUMP_STAT(ahstack, out_discards); 3336 ip_drop_packet(data_mp, B_FALSE, ixa->ixa_nce->nce_ill, 3337 DROPPER(ipss, ipds_ah_bad_v4_opts), 3338 &ahstack->ah_dropper); 3339 BUMP_MIB(ill->ill_ip_mib, ipIfStatsOutDiscards); 3340 if (need_refrele) 3341 ixa_refrele(ixa); 3342 return (NULL); 3343 } 3344 3345 phdr_mp->b_cont = data_mp; 3346 data_mp->b_rptr += length_to_skip; 3347 data_mp = phdr_mp; 3348 3349 /* 3350 * At this point data_mp points to 3351 * an mblk containing the pseudo header (IP header, 3352 * AH header, and ICV with mutable fields zero'ed out). 3353 * mp points to the mblk containing the ULP data. The original 3354 * IP header is kept before the ULP data in data_mp. 3355 */ 3356 3357 /* submit MAC request to KCF */ 3358 data_mp = ah_submit_req_outbound(data_mp, ixa, length_to_skip, assoc); 3359 if (need_refrele) 3360 ixa_refrele(ixa); 3361 return (data_mp); 3362 } 3363 3364 static mblk_t * 3365 ah_inbound(mblk_t *data_mp, void *arg, ip_recv_attr_t *ira) 3366 { 3367 ah_t *ah = (ah_t *)arg; 3368 ipsa_t *assoc = ira->ira_ipsec_ah_sa; 3369 int length_to_skip; 3370 int ah_length; 3371 mblk_t *phdr_mp; 3372 uint32_t ah_offset; 3373 netstack_t *ns = ira->ira_ill->ill_ipst->ips_netstack; 3374 ipsecah_stack_t *ahstack = ns->netstack_ipsecah; 3375 ipsec_stack_t *ipss = ns->netstack_ipsec; 3376 3377 ASSERT(assoc != NULL); 3378 3379 /* 3380 * We may wish to check replay in-range-only here as an optimization. 3381 * Include the reality check of ipsa->ipsa_replay > 3382 * ipsa->ipsa_replay_wsize for times when it's the first N packets, 3383 * where N == ipsa->ipsa_replay_wsize. 3384 * 3385 * Another check that may come here later is the "collision" check. 3386 * If legitimate packets flow quickly enough, this won't be a problem, 3387 * but collisions may cause authentication algorithm crunching to 3388 * take place when it doesn't need to. 3389 */ 3390 if (!sadb_replay_peek(assoc, ah->ah_replay)) { 3391 AH_BUMP_STAT(ahstack, replay_early_failures); 3392 IP_AH_BUMP_STAT(ipss, in_discards); 3393 ip_drop_packet(data_mp, B_TRUE, ira->ira_ill, 3394 DROPPER(ipss, ipds_ah_early_replay), 3395 &ahstack->ah_dropper); 3396 BUMP_MIB(ira->ira_ill->ill_ip_mib, ipIfStatsInDiscards); 3397 return (NULL); 3398 } 3399 3400 /* 3401 * The offset of the AH header can be computed from its pointer 3402 * within the data mblk, which was pulled up until the AH header 3403 * by ipsec_inbound_ah_sa() during SA selection. 3404 */ 3405 ah_offset = (uchar_t *)ah - data_mp->b_rptr; 3406 3407 /* 3408 * We need to pullup until the ICV before we call 3409 * ah_process_ip_options_v6. 3410 */ 3411 ah_length = (ah->ah_length << 2) + 8; 3412 3413 /* 3414 * NOTE : If we want to use any field of IP/AH header, you need 3415 * to re-assign following the pullup. 3416 */ 3417 if (((uchar_t *)ah + ah_length) > data_mp->b_wptr) { 3418 if (!pullupmsg(data_mp, (uchar_t *)ah + ah_length - 3419 data_mp->b_rptr)) { 3420 (void) ipsec_rl_strlog(ns, info.mi_idnum, 0, 0, 3421 SL_WARN | SL_ERROR, 3422 "ah_inbound: Small AH header\n"); 3423 IP_AH_BUMP_STAT(ipss, in_discards); 3424 ip_drop_packet(data_mp, B_TRUE, ira->ira_ill, 3425 DROPPER(ipss, ipds_ah_nomem), 3426 &ahstack->ah_dropper); 3427 BUMP_MIB(ira->ira_ill->ill_ip_mib, ipIfStatsInDiscards); 3428 return (NULL); 3429 } 3430 } 3431 3432 /* 3433 * Insert pseudo header: 3434 * [IP, ULP] => [IP, AH, ICV] -> ULP 3435 */ 3436 if (ira->ira_flags & IRAF_IS_IPV4) { 3437 phdr_mp = ah_process_ip_options_v4(data_mp, assoc, 3438 &length_to_skip, assoc->ipsa_mac_len, B_FALSE, ahstack); 3439 } else { 3440 phdr_mp = ah_process_ip_options_v6(data_mp, assoc, 3441 &length_to_skip, assoc->ipsa_mac_len, B_FALSE, ahstack); 3442 } 3443 3444 if (phdr_mp == NULL) { 3445 IP_AH_BUMP_STAT(ipss, in_discards); 3446 ip_drop_packet(data_mp, B_TRUE, ira->ira_ill, 3447 ((ira->ira_flags & IRAF_IS_IPV4) ? 3448 DROPPER(ipss, ipds_ah_bad_v4_opts) : 3449 DROPPER(ipss, ipds_ah_bad_v6_hdrs)), 3450 &ahstack->ah_dropper); 3451 BUMP_MIB(ira->ira_ill->ill_ip_mib, ipIfStatsInDiscards); 3452 return (NULL); 3453 } 3454 3455 phdr_mp->b_cont = data_mp; 3456 data_mp->b_rptr += length_to_skip; 3457 data_mp = phdr_mp; 3458 3459 /* submit request to KCF */ 3460 return (ah_submit_req_inbound(data_mp, ira, length_to_skip, ah_offset, 3461 assoc)); 3462 } 3463 3464 /* 3465 * Invoked after processing of an inbound packet by the 3466 * kernel crypto framework. Called by ah_submit_req() for a sync request, 3467 * or by the kcf callback for an async request. 3468 * Returns NULL if the mblk chain is consumed. 3469 */ 3470 static mblk_t * 3471 ah_auth_in_done(mblk_t *phdr_mp, ip_recv_attr_t *ira, ipsec_crypto_t *ic) 3472 { 3473 ipha_t *ipha; 3474 uint_t ah_offset = 0; 3475 mblk_t *mp; 3476 int align_len, newpos; 3477 ah_t *ah; 3478 uint32_t length; 3479 uint32_t *dest32; 3480 uint8_t *dest; 3481 boolean_t isv4; 3482 ip6_t *ip6h; 3483 uint_t icv_len; 3484 ipsa_t *assoc; 3485 kstat_named_t *counter; 3486 netstack_t *ns = ira->ira_ill->ill_ipst->ips_netstack; 3487 ipsecah_stack_t *ahstack = ns->netstack_ipsecah; 3488 ipsec_stack_t *ipss = ns->netstack_ipsec; 3489 3490 isv4 = (ira->ira_flags & IRAF_IS_IPV4); 3491 assoc = ira->ira_ipsec_ah_sa; 3492 icv_len = (uint_t)ic->ic_crypto_mac.cd_raw.iov_len; 3493 3494 if (phdr_mp == NULL) { 3495 ip_drop_packet(phdr_mp, B_TRUE, ira->ira_ill, 3496 DROPPER(ipss, ipds_ah_nomem), 3497 &ahstack->ah_dropper); 3498 BUMP_MIB(ira->ira_ill->ill_ip_mib, ipIfStatsInDiscards); 3499 return (NULL); 3500 } 3501 3502 mp = phdr_mp->b_cont; 3503 if (mp == NULL) { 3504 ip_drop_packet(phdr_mp, B_TRUE, ira->ira_ill, 3505 DROPPER(ipss, ipds_ah_nomem), 3506 &ahstack->ah_dropper); 3507 BUMP_MIB(ira->ira_ill->ill_ip_mib, ipIfStatsInDiscards); 3508 return (NULL); 3509 } 3510 mp->b_rptr -= ic->ic_skip_len; 3511 3512 ah_set_usetime(assoc, B_TRUE); 3513 3514 if (isv4) { 3515 ipha = (ipha_t *)mp->b_rptr; 3516 ah_offset = ipha->ipha_version_and_hdr_length - 3517 (uint8_t)((IP_VERSION << 4)); 3518 ah_offset <<= 2; 3519 align_len = P2ALIGN(icv_len + IPV4_PADDING_ALIGN - 1, 3520 IPV4_PADDING_ALIGN); 3521 } else { 3522 ip6h = (ip6_t *)mp->b_rptr; 3523 ah_offset = ipsec_ah_get_hdr_size_v6(mp, B_TRUE); 3524 ASSERT((mp->b_wptr - mp->b_rptr) >= ah_offset); 3525 align_len = P2ALIGN(icv_len + IPV6_PADDING_ALIGN - 1, 3526 IPV6_PADDING_ALIGN); 3527 } 3528 3529 ah = (ah_t *)(mp->b_rptr + ah_offset); 3530 newpos = sizeof (ah_t) + align_len; 3531 3532 /* 3533 * We get here only when authentication passed. 3534 */ 3535 3536 ah3dbg(ahstack, ("AH succeeded, checking replay\n")); 3537 AH_BUMP_STAT(ahstack, good_auth); 3538 3539 if (!sadb_replay_check(assoc, ah->ah_replay)) { 3540 int af; 3541 void *addr; 3542 3543 if (isv4) { 3544 addr = &ipha->ipha_dst; 3545 af = AF_INET; 3546 } else { 3547 addr = &ip6h->ip6_dst; 3548 af = AF_INET6; 3549 } 3550 3551 /* 3552 * Log the event. As of now we print out an event. 3553 * Do not print the replay failure number, or else 3554 * syslog cannot collate the error messages. Printing 3555 * the replay number that failed (or printing to the 3556 * console) opens a denial-of-service attack. 3557 */ 3558 AH_BUMP_STAT(ahstack, replay_failures); 3559 ipsec_assocfailure(info.mi_idnum, 0, 0, 3560 SL_ERROR | SL_WARN, 3561 "Replay failed for AH spi %x, dst_addr %s", 3562 assoc->ipsa_spi, addr, af, ahstack->ipsecah_netstack); 3563 counter = DROPPER(ipss, ipds_ah_replay); 3564 goto ah_in_discard; 3565 } 3566 3567 /* 3568 * We need to remove the AH header from the original 3569 * datagram. Best way to do this is to move the pre-AH headers 3570 * forward in the (relatively simple) IPv4 case. In IPv6, it's 3571 * a bit more complicated because of IPv6's next-header chaining, 3572 * but it's doable. 3573 */ 3574 if (isv4) { 3575 /* 3576 * Assign the right protocol, adjust the length as we 3577 * are removing the AH header and adjust the checksum to 3578 * account for the protocol and length. 3579 */ 3580 length = ntohs(ipha->ipha_length); 3581 if (!ah_age_bytes(assoc, length, B_TRUE)) { 3582 /* The ipsa has hit hard expiration, LOG and AUDIT. */ 3583 ipsec_assocfailure(info.mi_idnum, 0, 0, 3584 SL_ERROR | SL_WARN, 3585 "AH Association 0x%x, dst %s had bytes expire.\n", 3586 assoc->ipsa_spi, assoc->ipsa_dstaddr, 3587 AF_INET, ahstack->ipsecah_netstack); 3588 AH_BUMP_STAT(ahstack, bytes_expired); 3589 counter = DROPPER(ipss, ipds_ah_bytes_expire); 3590 goto ah_in_discard; 3591 } 3592 ipha->ipha_protocol = ah->ah_nexthdr; 3593 length -= newpos; 3594 3595 ipha->ipha_length = htons((uint16_t)length); 3596 ipha->ipha_hdr_checksum = 0; 3597 ipha->ipha_hdr_checksum = (uint16_t)ip_csum_hdr(ipha); 3598 } else { 3599 uchar_t *whereptr; 3600 int hdrlen; 3601 uint8_t *nexthdr; 3602 ip6_hbh_t *hbhhdr; 3603 ip6_dest_t *dsthdr; 3604 ip6_rthdr0_t *rthdr; 3605 3606 /* 3607 * Make phdr_mp hold until the AH header and make 3608 * mp hold everything past AH header. 3609 */ 3610 length = ntohs(ip6h->ip6_plen); 3611 if (!ah_age_bytes(assoc, length + sizeof (ip6_t), B_TRUE)) { 3612 /* The ipsa has hit hard expiration, LOG and AUDIT. */ 3613 ipsec_assocfailure(info.mi_idnum, 0, 0, 3614 SL_ERROR | SL_WARN, 3615 "AH Association 0x%x, dst %s had bytes " 3616 "expire.\n", assoc->ipsa_spi, &ip6h->ip6_dst, 3617 AF_INET6, ahstack->ipsecah_netstack); 3618 AH_BUMP_STAT(ahstack, bytes_expired); 3619 counter = DROPPER(ipss, ipds_ah_bytes_expire); 3620 goto ah_in_discard; 3621 } 3622 3623 /* 3624 * Update the next header field of the header preceding 3625 * AH with the next header field of AH. Start with the 3626 * IPv6 header and proceed with the extension headers 3627 * until we find what we're looking for. 3628 */ 3629 nexthdr = &ip6h->ip6_nxt; 3630 whereptr = (uchar_t *)ip6h; 3631 hdrlen = sizeof (ip6_t); 3632 3633 while (*nexthdr != IPPROTO_AH) { 3634 whereptr += hdrlen; 3635 /* Assume IP has already stripped it */ 3636 ASSERT(*nexthdr != IPPROTO_FRAGMENT); 3637 switch (*nexthdr) { 3638 case IPPROTO_HOPOPTS: 3639 hbhhdr = (ip6_hbh_t *)whereptr; 3640 nexthdr = &hbhhdr->ip6h_nxt; 3641 hdrlen = 8 * (hbhhdr->ip6h_len + 1); 3642 break; 3643 case IPPROTO_DSTOPTS: 3644 dsthdr = (ip6_dest_t *)whereptr; 3645 nexthdr = &dsthdr->ip6d_nxt; 3646 hdrlen = 8 * (dsthdr->ip6d_len + 1); 3647 break; 3648 case IPPROTO_ROUTING: 3649 rthdr = (ip6_rthdr0_t *)whereptr; 3650 nexthdr = &rthdr->ip6r0_nxt; 3651 hdrlen = 8 * (rthdr->ip6r0_len + 1); 3652 break; 3653 } 3654 } 3655 *nexthdr = ah->ah_nexthdr; 3656 length -= newpos; 3657 ip6h->ip6_plen = htons((uint16_t)length); 3658 } 3659 3660 /* Now that we've fixed the IP header, move it forward. */ 3661 mp->b_rptr += newpos; 3662 if (IS_P2ALIGNED(mp->b_rptr, sizeof (uint32_t))) { 3663 dest32 = (uint32_t *)(mp->b_rptr + ah_offset); 3664 while (--dest32 >= (uint32_t *)mp->b_rptr) 3665 *dest32 = *(dest32 - (newpos >> 2)); 3666 } else { 3667 dest = mp->b_rptr + ah_offset; 3668 while (--dest >= mp->b_rptr) 3669 *dest = *(dest - newpos); 3670 } 3671 freeb(phdr_mp); 3672 3673 /* 3674 * If SA is labelled, use its label, else inherit the label 3675 */ 3676 if (is_system_labeled() && (assoc->ipsa_tsl != NULL)) { 3677 if (!ip_recv_attr_replace_label(ira, assoc->ipsa_tsl)) { 3678 ip_drop_packet(mp, B_TRUE, ira->ira_ill, 3679 DROPPER(ipss, ipds_ah_nomem), &ahstack->ah_dropper); 3680 BUMP_MIB(ira->ira_ill->ill_ip_mib, ipIfStatsInDiscards); 3681 return (NULL); 3682 } 3683 } 3684 3685 if (assoc->ipsa_state == IPSA_STATE_IDLE) { 3686 /* 3687 * Cluster buffering case. Tell caller that we're 3688 * handling the packet. 3689 */ 3690 sadb_buf_pkt(assoc, mp, ira); 3691 return (NULL); 3692 } 3693 3694 return (mp); 3695 3696 ah_in_discard: 3697 IP_AH_BUMP_STAT(ipss, in_discards); 3698 ip_drop_packet(phdr_mp, B_TRUE, ira->ira_ill, counter, 3699 &ahstack->ah_dropper); 3700 BUMP_MIB(ira->ira_ill->ill_ip_mib, ipIfStatsInDiscards); 3701 return (NULL); 3702 } 3703 3704 /* 3705 * Invoked after processing of an outbound packet by the 3706 * kernel crypto framework, either by ah_submit_req() for a request 3707 * executed syncrhonously, or by the KEF callback for a request 3708 * executed asynchronously. 3709 */ 3710 static mblk_t * 3711 ah_auth_out_done(mblk_t *phdr_mp, ip_xmit_attr_t *ixa, ipsec_crypto_t *ic) 3712 { 3713 mblk_t *mp; 3714 int align_len; 3715 uint32_t hdrs_length; 3716 uchar_t *ptr; 3717 uint32_t length; 3718 boolean_t isv4; 3719 size_t icv_len; 3720 netstack_t *ns = ixa->ixa_ipst->ips_netstack; 3721 ipsecah_stack_t *ahstack = ns->netstack_ipsecah; 3722 ipsec_stack_t *ipss = ns->netstack_ipsec; 3723 ill_t *ill = ixa->ixa_nce->nce_ill; 3724 3725 isv4 = (ixa->ixa_flags & IXAF_IS_IPV4); 3726 icv_len = ic->ic_crypto_mac.cd_raw.iov_len; 3727 3728 mp = phdr_mp->b_cont; 3729 if (mp == NULL) { 3730 ip_drop_packet(phdr_mp, B_FALSE, ill, 3731 DROPPER(ipss, ipds_ah_nomem), 3732 &ahstack->ah_dropper); 3733 BUMP_MIB(ill->ill_ip_mib, ipIfStatsOutDiscards); 3734 return (NULL); 3735 } 3736 mp->b_rptr -= ic->ic_skip_len; 3737 3738 ASSERT(ixa->ixa_flags & IXAF_IPSEC_SECURE); 3739 ASSERT(ixa->ixa_ipsec_ah_sa != NULL); 3740 ah_set_usetime(ixa->ixa_ipsec_ah_sa, B_FALSE); 3741 3742 if (isv4) { 3743 ipha_t *ipha; 3744 ipha_t *nipha; 3745 3746 ipha = (ipha_t *)mp->b_rptr; 3747 hdrs_length = ipha->ipha_version_and_hdr_length - 3748 (uint8_t)((IP_VERSION << 4)); 3749 hdrs_length <<= 2; 3750 align_len = P2ALIGN(icv_len + IPV4_PADDING_ALIGN - 1, 3751 IPV4_PADDING_ALIGN); 3752 /* 3753 * phdr_mp must have the right amount of space for the 3754 * combined IP and AH header. Copy the IP header and 3755 * the ack_data onto AH. Note that the AH header was 3756 * already formed before the ICV calculation and hence 3757 * you don't have to copy it here. 3758 */ 3759 bcopy(mp->b_rptr, phdr_mp->b_rptr, hdrs_length); 3760 3761 ptr = phdr_mp->b_rptr + hdrs_length + sizeof (ah_t); 3762 bcopy(phdr_mp->b_wptr, ptr, icv_len); 3763 3764 /* 3765 * Compute the new header checksum as we are assigning 3766 * IPPROTO_AH and adjusting the length here. 3767 */ 3768 nipha = (ipha_t *)phdr_mp->b_rptr; 3769 3770 nipha->ipha_protocol = IPPROTO_AH; 3771 length = ntohs(nipha->ipha_length); 3772 length += (sizeof (ah_t) + align_len); 3773 nipha->ipha_length = htons((uint16_t)length); 3774 nipha->ipha_hdr_checksum = 0; 3775 nipha->ipha_hdr_checksum = (uint16_t)ip_csum_hdr(nipha); 3776 } else { 3777 ip6_t *ip6h; 3778 ip6_t *nip6h; 3779 uint_t ah_offset; 3780 3781 ip6h = (ip6_t *)mp->b_rptr; 3782 nip6h = (ip6_t *)phdr_mp->b_rptr; 3783 align_len = P2ALIGN(icv_len + IPV6_PADDING_ALIGN - 1, 3784 IPV6_PADDING_ALIGN); 3785 /* 3786 * phdr_mp must have the right amount of space for the 3787 * combined IP and AH header. Copy the IP header with 3788 * options into the pseudo header. When we constructed 3789 * a pseudo header, we did not copy some of the mutable 3790 * fields. We do it now by calling ah_fix_phdr_v6() 3791 * with the last argument B_TRUE. It returns the 3792 * ah_offset into the pseudo header. 3793 */ 3794 3795 bcopy(ip6h, nip6h, IPV6_HDR_LEN); 3796 ah_offset = ah_fix_phdr_v6(nip6h, ip6h, B_TRUE, B_TRUE); 3797 ASSERT(ah_offset != 0); 3798 /* 3799 * phdr_mp can hold exactly the whole IP header with options 3800 * plus the AH header also. Thus subtracting the AH header's 3801 * size should give exactly how much of the original header 3802 * should be skipped. 3803 */ 3804 hdrs_length = (phdr_mp->b_wptr - phdr_mp->b_rptr) - 3805 sizeof (ah_t) - icv_len; 3806 bcopy(phdr_mp->b_wptr, ((uint8_t *)nip6h + ah_offset + 3807 sizeof (ah_t)), icv_len); 3808 length = ntohs(nip6h->ip6_plen); 3809 length += (sizeof (ah_t) + align_len); 3810 nip6h->ip6_plen = htons((uint16_t)length); 3811 } 3812 3813 /* Skip the original IP header */ 3814 mp->b_rptr += hdrs_length; 3815 if (mp->b_rptr == mp->b_wptr) { 3816 phdr_mp->b_cont = mp->b_cont; 3817 freeb(mp); 3818 } 3819 3820 return (phdr_mp); 3821 } 3822 3823 /* Refactor me */ 3824 /* 3825 * Wrapper to allow IP to trigger an AH association failure message 3826 * during SA inbound selection. 3827 */ 3828 void 3829 ipsecah_in_assocfailure(mblk_t *mp, char level, ushort_t sl, char *fmt, 3830 uint32_t spi, void *addr, int af, ip_recv_attr_t *ira) 3831 { 3832 netstack_t *ns = ira->ira_ill->ill_ipst->ips_netstack; 3833 ipsecah_stack_t *ahstack = ns->netstack_ipsecah; 3834 ipsec_stack_t *ipss = ns->netstack_ipsec; 3835 3836 if (ahstack->ipsecah_log_unknown_spi) { 3837 ipsec_assocfailure(info.mi_idnum, 0, level, sl, fmt, spi, 3838 addr, af, ahstack->ipsecah_netstack); 3839 } 3840 3841 ip_drop_packet(mp, B_TRUE, ira->ira_ill, 3842 DROPPER(ipss, ipds_ah_no_sa), 3843 &ahstack->ah_dropper); 3844 } 3845 3846 /* 3847 * Initialize the AH input and output processing functions. 3848 */ 3849 void 3850 ipsecah_init_funcs(ipsa_t *sa) 3851 { 3852 if (sa->ipsa_output_func == NULL) 3853 sa->ipsa_output_func = ah_outbound; 3854 if (sa->ipsa_input_func == NULL) 3855 sa->ipsa_input_func = ah_inbound; 3856 } 3857