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