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