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