4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include <sys/types.h>
27 #include <sys/stream.h>
28 #include <sys/stropts.h>
29 #include <sys/errno.h>
30 #include <sys/strlog.h>
31 #include <sys/tihdr.h>
32 #include <sys/socket.h>
33 #include <sys/ddi.h>
34 #include <sys/sunddi.h>
35 #include <sys/mkdev.h>
36 #include <sys/kmem.h>
37 #include <sys/zone.h>
38 #include <sys/sysmacros.h>
39 #include <sys/cmn_err.h>
40 #include <sys/vtrace.h>
41 #include <sys/debug.h>
42 #include <sys/atomic.h>
43 #include <sys/strsun.h>
78 * ipsecah_g_nd in ipsecah_init_nd.
79 * All of these are alterable, within the min/max values given, at run time.
80 */
81 static ipsecahparam_t lcl_param_arr[] = {
82 /* min max value name */
83 { 0, 3, 0, "ipsecah_debug"},
84 { 125, 32000, SADB_AGE_INTERVAL_DEFAULT, "ipsecah_age_interval"},
85 { 1, 10, 1, "ipsecah_reap_delay"},
86 { 1, SADB_MAX_REPLAY, 64, "ipsecah_replay_size"},
87 { 1, 300, 15, "ipsecah_acquire_timeout"},
88 { 1, 1800, 90, "ipsecah_larval_timeout"},
89 /* Default lifetime values for ACQUIRE messages. */
90 { 0, 0xffffffffU, 0, "ipsecah_default_soft_bytes"},
91 { 0, 0xffffffffU, 0, "ipsecah_default_hard_bytes"},
92 { 0, 0xffffffffU, 24000, "ipsecah_default_soft_addtime"},
93 { 0, 0xffffffffU, 28800, "ipsecah_default_hard_addtime"},
94 { 0, 0xffffffffU, 0, "ipsecah_default_soft_usetime"},
95 { 0, 0xffffffffU, 0, "ipsecah_default_hard_usetime"},
96 { 0, 1, 0, "ipsecah_log_unknown_spi"},
97 };
98 #define ipsecah_debug ipsecah_params[0].ipsecah_param_value
99 #define ipsecah_age_interval ipsecah_params[1].ipsecah_param_value
100 #define ipsecah_age_int_max ipsecah_params[1].ipsecah_param_max
101 #define ipsecah_reap_delay ipsecah_params[2].ipsecah_param_value
102 #define ipsecah_replay_size ipsecah_params[3].ipsecah_param_value
103 #define ipsecah_acquire_timeout ipsecah_params[4].ipsecah_param_value
104 #define ipsecah_larval_timeout ipsecah_params[5].ipsecah_param_value
105 #define ipsecah_default_soft_bytes ipsecah_params[6].ipsecah_param_value
106 #define ipsecah_default_hard_bytes ipsecah_params[7].ipsecah_param_value
107 #define ipsecah_default_soft_addtime ipsecah_params[8].ipsecah_param_value
108 #define ipsecah_default_hard_addtime ipsecah_params[9].ipsecah_param_value
109 #define ipsecah_default_soft_usetime ipsecah_params[10].ipsecah_param_value
110 #define ipsecah_default_hard_usetime ipsecah_params[11].ipsecah_param_value
111 #define ipsecah_log_unknown_spi ipsecah_params[12].ipsecah_param_value
112
113 #define ah0dbg(a) printf a
114 /* NOTE: != 0 instead of > 0 so lint doesn't complain. */
115 #define ah1dbg(ahstack, a) if (ahstack->ipsecah_debug != 0) printf a
116 #define ah2dbg(ahstack, a) if (ahstack->ipsecah_debug > 1) printf a
117 #define ah3dbg(ahstack, a) if (ahstack->ipsecah_debug > 2) printf a
118
119 /*
120 * XXX This is broken. Padding should be determined dynamically
121 * depending on the ICV size and IP version number so that the
122 * total AH header size is a multiple of 32 bits or 64 bits
123 * for V4 and V6 respectively. For 96bit ICVs we have no problems.
124 * Anything different from that, we need to fix our code.
125 */
126 #define IPV4_PADDING_ALIGN 0x04 /* Multiple of 32 bits */
127 #define IPV6_PADDING_ALIGN 0x04 /* Multiple of 32 bits */
128
129 /*
130 * Helper macro. Avoids a call to msgdsize if there is only one
131 * mblk in the chain.
132 */
133 #define AH_MSGSIZE(mp) ((mp)->b_cont != NULL ? msgdsize(mp) : MBLKL(mp))
134
135
136 static mblk_t *ah_auth_out_done(mblk_t *, ip_xmit_attr_t *, ipsec_crypto_t *);
137 static mblk_t *ah_auth_in_done(mblk_t *, ip_recv_attr_t *, ipsec_crypto_t *);
138 static mblk_t *ah_process_ip_options_v4(mblk_t *, ipsa_t *, int *, uint_t,
139 boolean_t, ipsecah_stack_t *);
140 static mblk_t *ah_process_ip_options_v6(mblk_t *, ipsa_t *, int *, uint_t,
141 boolean_t, ipsecah_stack_t *);
142 static void ah_getspi(mblk_t *, keysock_in_t *, ipsecah_stack_t *);
143 static void ah_inbound_restart(mblk_t *, ip_recv_attr_t *);
144
145 static mblk_t *ah_outbound(mblk_t *, ip_xmit_attr_t *);
146 static void ah_outbound_finish(mblk_t *, ip_xmit_attr_t *);
147
148 static int ipsecah_open(queue_t *, dev_t *, int, int, cred_t *);
149 static int ipsecah_close(queue_t *);
150 static void ipsecah_wput(queue_t *, mblk_t *);
151 static void ah_send_acquire(ipsacq_t *, mblk_t *, netstack_t *);
152 static boolean_t ah_register_out(uint32_t, uint32_t, uint_t, ipsecah_stack_t *,
153 cred_t *);
154 static void *ipsecah_stack_init(netstackid_t stackid, netstack_t *ns);
155 static void ipsecah_stack_fini(netstackid_t stackid, void *arg);
156
157 /* Setable in /etc/system */
158 uint32_t ah_hash_size = IPSEC_DEFAULT_HASH_SIZE;
159
160 static taskq_t *ah_taskq;
161
162 static struct module_info info = {
163 5136, "ipsecah", 0, INFPSZ, 65536, 1024
164 };
165
166 static struct qinit rinit = {
167 (pfi_t)putnext, NULL, ipsecah_open, ipsecah_close, NULL, &info,
168 NULL
169 };
170
171 static struct qinit winit = {
230 netstackid_t stackid = (netstackid_t)(uintptr_t)kp->ks_private;
231 netstack_t *ns;
232 ipsec_stack_t *ipss;
233
234 if ((kp == NULL) || (kp->ks_data == NULL))
235 return (EIO);
236
237 if (rw == KSTAT_WRITE)
238 return (EACCES);
239
240 ns = netstack_find_by_stackid(stackid);
241 if (ns == NULL)
242 return (-1);
243 ipss = ns->netstack_ipsec;
244 if (ipss == NULL) {
245 netstack_rele(ns);
246 return (-1);
247 }
248 ekp = (ah_kstats_t *)kp->ks_data;
249
250 mutex_enter(&ipss->ipsec_alg_lock);
251 ekp->ah_stat_num_aalgs.value.ui64 = ipss->ipsec_nalgs[IPSEC_ALG_AUTH];
252 mutex_exit(&ipss->ipsec_alg_lock);
253
254 netstack_rele(ns);
255 return (0);
256 }
257
258 /*
259 * Don't have to lock ipsec_age_interval, as only one thread will access it at
260 * a time, because I control the one function that does a qtimeout() on
261 * ah_pfkey_q.
262 */
263 static void
264 ah_ager(void *arg)
265 {
266 ipsecah_stack_t *ahstack = (ipsecah_stack_t *)arg;
267 netstack_t *ns = ahstack->ipsecah_netstack;
268 hrtime_t begin = gethrtime();
269
270 sadb_ager(&ahstack->ah_sadb.s_v4, ahstack->ah_pfkey_q,
271 ahstack->ipsecah_reap_delay, ns);
272 sadb_ager(&ahstack->ah_sadb.s_v6, ahstack->ah_pfkey_q,
402 */
403 static void *
404 ipsecah_stack_init(netstackid_t stackid, netstack_t *ns)
405 {
406 ipsecah_stack_t *ahstack;
407 ipsecahparam_t *ahp;
408
409 ahstack = (ipsecah_stack_t *)kmem_zalloc(sizeof (*ahstack), KM_SLEEP);
410 ahstack->ipsecah_netstack = ns;
411
412 ahp = (ipsecahparam_t *)kmem_alloc(sizeof (lcl_param_arr), KM_SLEEP);
413 ahstack->ipsecah_params = ahp;
414 bcopy(lcl_param_arr, ahp, sizeof (lcl_param_arr));
415
416 (void) ipsecah_param_register(&ahstack->ipsecah_g_nd, ahp,
417 A_CNT(lcl_param_arr));
418
419 (void) ah_kstat_init(ahstack, stackid);
420
421 ahstack->ah_sadb.s_acquire_timeout = &ahstack->ipsecah_acquire_timeout;
422 ahstack->ah_sadb.s_acqfn = ah_send_acquire;
423 sadbp_init("AH", &ahstack->ah_sadb, SADB_SATYPE_AH, ah_hash_size,
424 ahstack->ipsecah_netstack);
425
426 mutex_init(&ahstack->ipsecah_param_lock, NULL, MUTEX_DEFAULT, 0);
427
428 ip_drop_register(&ahstack->ah_dropper, "IPsec AH");
429 return (ahstack);
430 }
431
432 /*
433 * Destroy things for AH at module unload time.
434 */
435 void
436 ipsecah_ddi_destroy(void)
437 {
438 netstack_unregister(NS_IPSECAH);
439 taskq_destroy(ah_taskq);
440 }
441
442 /*
443 * Destroy things for AH for one stack... Never called?
444 */
445 static void
446 ipsecah_stack_fini(netstackid_t stackid, void *arg)
447 {
448 ipsecah_stack_t *ahstack = (ipsecah_stack_t *)arg;
449
450 if (ahstack->ah_pfkey_q != NULL) {
451 (void) quntimeout(ahstack->ah_pfkey_q, ahstack->ah_event);
452 }
453 ahstack->ah_sadb.s_acqfn = NULL;
454 ahstack->ah_sadb.s_acquire_timeout = NULL;
455 sadbp_destroy(&ahstack->ah_sadb, ahstack->ipsecah_netstack);
456 ip_drop_unregister(&ahstack->ah_dropper);
457 mutex_destroy(&ahstack->ipsecah_param_lock);
458 nd_free(&ahstack->ipsecah_g_nd);
459
460 kmem_free(ahstack->ipsecah_params, sizeof (lcl_param_arr));
461 ahstack->ipsecah_params = NULL;
462 kstat_delete_netstack(ahstack->ah_ksp, stackid);
463 ahstack->ah_ksp = NULL;
464 ahstack->ah_kstats = NULL;
465
466 kmem_free(ahstack, sizeof (*ahstack));
467 }
468
469 /*
470 * AH module open routine, which is here for keysock plumbing.
471 * Keysock is pushed over {AH,ESP} which is an artifact from the Bad Old
472 * Days of export control, and fears that ESP would not be allowed
473 * to be shipped at all by default. Eventually, keysock should
556 mp = sadb_keysock_out(serial);
557 if (mp == NULL) {
558 ah0dbg(("ah_register_out: couldn't allocate mblk.\n"));
559 return (B_FALSE);
560 }
561
562 if (is_system_labeled() && (cr != NULL)) {
563 sens_tsl = crgetlabel(cr);
564 if (sens_tsl != NULL) {
565 sens_len = sadb_sens_len_from_label(sens_tsl);
566 allocsize += sens_len;
567 }
568 }
569
570 /*
571 * Allocate the PF_KEY message that follows KEYSOCK_OUT.
572 * The alg reader lock needs to be held while allocating
573 * the variable part (i.e. the algorithms) of the message.
574 */
575
576 mutex_enter(&ipss->ipsec_alg_lock);
577
578 /*
579 * Return only valid algorithms, so the number of algorithms
580 * to send up may be less than the number of algorithm entries
581 * in the table.
582 */
583 authalgs = ipss->ipsec_alglists[IPSEC_ALG_AUTH];
584 for (num_aalgs = 0, i = 0; i < IPSEC_MAX_ALGS; i++)
585 if (authalgs[i] != NULL && ALG_VALID(authalgs[i]))
586 num_aalgs++;
587
588 /*
589 * Fill SADB_REGISTER message's algorithm descriptors. Hold
590 * down the lock while filling it.
591 */
592 if (num_aalgs != 0) {
593 allocsize += (num_aalgs * sizeof (*saalg));
594 allocsize += sizeof (*sasupp);
595 }
596 mp->b_cont = allocb(allocsize, BPRI_HI);
597 if (mp->b_cont == NULL) {
598 mutex_exit(&ipss->ipsec_alg_lock);
599 freemsg(mp);
600 return (B_FALSE);
601 }
602
603 mp->b_cont->b_wptr += allocsize;
604 nextext = (sadb_ext_t *)(mp->b_cont->b_rptr + sizeof (*samsg));
605
606 if (num_aalgs != 0) {
607
608 saalg = (sadb_alg_t *)(((uint8_t *)nextext) + sizeof (*sasupp));
609 ASSERT(((ulong_t)saalg & 0x7) == 0);
610
611 numalgs_snap = 0;
612 for (i = 0;
613 ((i < IPSEC_MAX_ALGS) && (numalgs_snap < num_aalgs));
614 i++) {
615 if (authalgs[i] == NULL || !ALG_VALID(authalgs[i]))
616 continue;
617
618 saalg->sadb_alg_id = authalgs[i]->alg_id;
625 ASSERT(authalgs[i]->alg_saltlen == 0);
626 saalg->sadb_x_alg_saltbits =
627 SADB_8TO1(authalgs[i]->alg_saltlen);
628 numalgs_snap++;
629 saalg++;
630 }
631 ASSERT(numalgs_snap == num_aalgs);
632 #ifdef DEBUG
633 /*
634 * Reality check to make sure I snagged all of the
635 * algorithms.
636 */
637 for (; i < IPSEC_MAX_ALGS; i++)
638 if (authalgs[i] != NULL && ALG_VALID(authalgs[i]))
639 cmn_err(CE_PANIC,
640 "ah_register_out()! Missed #%d.\n", i);
641 #endif /* DEBUG */
642 nextext = (sadb_ext_t *)saalg;
643 }
644
645 mutex_exit(&ipss->ipsec_alg_lock);
646
647 if (sens_tsl != NULL) {
648 sens = (sadb_sens_t *)nextext;
649 sadb_sens_from_label(sens, SADB_EXT_SENSITIVITY,
650 sens_tsl, sens_len);
651
652 nextext = (sadb_ext_t *)(((uint8_t *)sens) + sens_len);
653 }
654
655 /* Now fill the restof the SADB_REGISTER message. */
656
657 samsg = (sadb_msg_t *)mp->b_cont->b_rptr;
658 samsg->sadb_msg_version = PF_KEY_V2;
659 samsg->sadb_msg_type = SADB_REGISTER;
660 samsg->sadb_msg_errno = 0;
661 samsg->sadb_msg_satype = SADB_SATYPE_AH;
662 samsg->sadb_msg_len = SADB_8TO64(allocsize);
663 samsg->sadb_msg_reserved = 0;
664 /*
665 * Assume caller has sufficient sequence/pid number info. If it's one
1106 /* Stuff I don't support, for now. XXX Diagnostic? */
1107 if (ksi->ks_in_extv[SADB_EXT_LIFETIME_CURRENT] != NULL)
1108 return (EOPNOTSUPP);
1109
1110 if (ksi->ks_in_extv[SADB_EXT_SENSITIVITY] != NULL) {
1111 if (!is_system_labeled())
1112 return (EOPNOTSUPP);
1113 }
1114
1115 if (ksi->ks_in_extv[SADB_X_EXT_OUTER_SENS] != NULL) {
1116 if (!is_system_labeled())
1117 return (EOPNOTSUPP);
1118 }
1119 /*
1120 * XXX Policy : I'm not checking identities at this time, but
1121 * if I did, I'd do them here, before I sent the weak key
1122 * check up to the algorithm.
1123 */
1124
1125 /* verify that there is a mapping for the specified algorithm */
1126 mutex_enter(&ipss->ipsec_alg_lock);
1127 aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH][assoc->sadb_sa_auth];
1128 if (aalg == NULL || !ALG_VALID(aalg)) {
1129 mutex_exit(&ipss->ipsec_alg_lock);
1130 ah1dbg(ahstack, ("Couldn't find auth alg #%d.\n",
1131 assoc->sadb_sa_auth));
1132 *diagnostic = SADB_X_DIAGNOSTIC_BAD_AALG;
1133 return (EINVAL);
1134 }
1135 ASSERT(aalg->alg_mech_type != CRYPTO_MECHANISM_INVALID);
1136
1137 /* sanity check key sizes */
1138 if (!ipsec_valid_key_size(key->sadb_key_bits, aalg)) {
1139 mutex_exit(&ipss->ipsec_alg_lock);
1140 *diagnostic = SADB_X_DIAGNOSTIC_BAD_AKEYBITS;
1141 return (EINVAL);
1142 }
1143
1144 /* check key and fix parity if needed */
1145 if (ipsec_check_key(aalg->alg_mech_type, key, B_TRUE,
1146 diagnostic) != 0) {
1147 mutex_exit(&ipss->ipsec_alg_lock);
1148 return (EINVAL);
1149 }
1150
1151 mutex_exit(&ipss->ipsec_alg_lock);
1152
1153 return (ah_add_sa_finish(mp, (sadb_msg_t *)mp->b_cont->b_rptr, ksi,
1154 diagnostic, ahstack));
1155 }
1156
1157 /* Refactor me */
1158 /*
1159 * Update a security association. Updates come in two varieties. The first
1160 * is an update of lifetimes on a non-larval SA. The second is an update of
1161 * a larval SA, which ends up looking a lot more like an add.
1162 */
1163 static int
1164 ah_update_sa(mblk_t *mp, keysock_in_t *ksi, int *diagnostic,
1165 ipsecah_stack_t *ahstack, uint8_t sadb_msg_type)
1166 {
1167 sadb_sa_t *assoc = (sadb_sa_t *)ksi->ks_in_extv[SADB_EXT_SA];
1168 sadb_address_t *dstext =
1169 (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_DST];
1170 mblk_t *buf_pkt;
1171 int rcode;
1718 }
1719
1720 inrc = sadb_age_bytes(ahstack->ah_pfkey_q, inassoc, bytes, B_TRUE);
1721 outrc = sadb_age_bytes(ahstack->ah_pfkey_q, outassoc, bytes, B_FALSE);
1722
1723 /*
1724 * REFRELE any peer SA.
1725 *
1726 * Because of the multi-line macro nature of IPSA_REFRELE, keep
1727 * them in { }.
1728 */
1729 if (inbound) {
1730 IPSA_REFRELE(outassoc);
1731 } else {
1732 IPSA_REFRELE(inassoc);
1733 }
1734
1735 return (inrc && outrc);
1736 }
1737
1738 /*
1739 * Perform the really difficult work of inserting the proposed situation.
1740 * Called while holding the algorithm lock.
1741 */
1742 static void
1743 ah_insert_prop(sadb_prop_t *prop, ipsacq_t *acqrec, uint_t combs,
1744 netstack_t *ns)
1745 {
1746 sadb_comb_t *comb = (sadb_comb_t *)(prop + 1);
1747 ipsec_action_t *ap;
1748 ipsec_prot_t *prot;
1749 ipsecah_stack_t *ahstack = ns->netstack_ipsecah;
1750 ipsec_stack_t *ipss = ns->netstack_ipsec;
1751
1752 ASSERT(MUTEX_HELD(&ipss->ipsec_alg_lock));
1753
1754 prop->sadb_prop_exttype = SADB_EXT_PROPOSAL;
1755 prop->sadb_prop_len = SADB_8TO64(sizeof (sadb_prop_t));
1756 *(uint32_t *)(&prop->sadb_prop_replay) = 0; /* Quick zero-out! */
1757
1758 prop->sadb_prop_replay = ahstack->ipsecah_replay_size;
1759
1760 /*
1761 * Based upon algorithm properties, and what-not, prioritize a
1762 * proposal, based on the ordering of the AH algorithms in the
1763 * alternatives in the policy rule or socket that was placed
1764 * in the acquire record.
1765 */
1766
1767 for (ap = acqrec->ipsacq_act; ap != NULL;
1768 ap = ap->ipa_next) {
1769 ipsec_alginfo_t *aalg;
1770
1771 if ((ap->ipa_act.ipa_type != IPSEC_POLICY_APPLY) ||
1772 (!ap->ipa_act.ipa_apply.ipp_use_ah))
1773 continue;
1774
1775 prot = &ap->ipa_act.ipa_apply;
1776
1777 ASSERT(prot->ipp_auth_alg > 0);
1778
1779 aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH]
1780 [prot->ipp_auth_alg];
1781 if (aalg == NULL || !ALG_VALID(aalg))
1782 continue;
1783
1784 /* XXX check aalg for duplicates??.. */
1785
1786 comb->sadb_comb_flags = 0;
1787 comb->sadb_comb_reserved = 0;
1788 comb->sadb_comb_encrypt = 0;
1789 comb->sadb_comb_encrypt_minbits = 0;
1790 comb->sadb_comb_encrypt_maxbits = 0;
1791
1792 comb->sadb_comb_auth = aalg->alg_id;
1793 comb->sadb_comb_auth_minbits =
1794 MAX(prot->ipp_ah_minbits, aalg->alg_ef_minbits);
1795 comb->sadb_comb_auth_maxbits =
1796 MIN(prot->ipp_ah_maxbits, aalg->alg_ef_maxbits);
1797
1798 /*
1799 * The following may be based on algorithm
1800 * properties, but in the meantime, we just pick
1801 * some good, sensible numbers. Key mgmt. can
1802 * (and perhaps should) be the place to finalize
1803 * such decisions.
1804 */
1805
1806 /*
1807 * No limits on allocations, since we really don't
1808 * support that concept currently.
1809 */
1810 comb->sadb_comb_soft_allocations = 0;
1811 comb->sadb_comb_hard_allocations = 0;
1812
1813 /*
1814 * These may want to come from policy rule..
1815 */
1816 comb->sadb_comb_soft_bytes =
1817 ahstack->ipsecah_default_soft_bytes;
1818 comb->sadb_comb_hard_bytes =
1819 ahstack->ipsecah_default_hard_bytes;
1820 comb->sadb_comb_soft_addtime =
1821 ahstack->ipsecah_default_soft_addtime;
1822 comb->sadb_comb_hard_addtime =
1823 ahstack->ipsecah_default_hard_addtime;
1824 comb->sadb_comb_soft_usetime =
1825 ahstack->ipsecah_default_soft_usetime;
1826 comb->sadb_comb_hard_usetime =
1827 ahstack->ipsecah_default_hard_usetime;
1828
1829 prop->sadb_prop_len += SADB_8TO64(sizeof (*comb));
1830 if (--combs == 0)
1831 return; /* out of space.. */
1832 comb++;
1833 }
1834 }
1835
1836 /*
1837 * Prepare and actually send the SADB_ACQUIRE message to PF_KEY.
1838 */
1839 static void
1840 ah_send_acquire(ipsacq_t *acqrec, mblk_t *extended, netstack_t *ns)
1841 {
1842 uint_t combs;
1843 sadb_msg_t *samsg;
1844 sadb_prop_t *prop;
1845 mblk_t *pfkeymp, *msgmp;
1846 ipsecah_stack_t *ahstack = ns->netstack_ipsecah;
1847 ipsec_stack_t *ipss = ns->netstack_ipsec;
1848
1849 AH_BUMP_STAT(ahstack, acquire_requests);
1850
1851 if (ahstack->ah_pfkey_q == NULL) {
1852 mutex_exit(&acqrec->ipsacq_lock);
1853 return;
1854 }
1855
1856 /* Set up ACQUIRE. */
1857 pfkeymp = sadb_setup_acquire(acqrec, SADB_SATYPE_AH,
1858 ns->netstack_ipsec);
1859 if (pfkeymp == NULL) {
1860 ah0dbg(("sadb_setup_acquire failed.\n"));
1861 mutex_exit(&acqrec->ipsacq_lock);
1862 return;
1863 }
1864 ASSERT(MUTEX_HELD(&ipss->ipsec_alg_lock));
1865 combs = ipss->ipsec_nalgs[IPSEC_ALG_AUTH];
1866 msgmp = pfkeymp->b_cont;
1867 samsg = (sadb_msg_t *)(msgmp->b_rptr);
1868
1869 /* Insert proposal here. */
1870
1871 prop = (sadb_prop_t *)(((uint64_t *)samsg) + samsg->sadb_msg_len);
1872 ah_insert_prop(prop, acqrec, combs, ns);
1873 samsg->sadb_msg_len += prop->sadb_prop_len;
1874 msgmp->b_wptr += SADB_64TO8(samsg->sadb_msg_len);
1875
1876 mutex_exit(&ipss->ipsec_alg_lock);
1877
1878 /*
1879 * Must mutex_exit() before sending PF_KEY message up, in
1880 * order to avoid recursive mutex_enter() if there are no registered
1881 * listeners.
1882 *
1883 * Once I've sent the message, I'm cool anyway.
1884 */
1885 mutex_exit(&acqrec->ipsacq_lock);
1886 if (extended != NULL) {
1887 putnext(ahstack->ah_pfkey_q, extended);
1888 }
1889 putnext(ahstack->ah_pfkey_q, pfkeymp);
1890 }
1891
1892 /* Refactor me */
1893 /*
1894 * Handle the SADB_GETSPI message. Create a larval SA.
1895 */
1896 static void
1897 ah_getspi(mblk_t *mp, keysock_in_t *ksi, ipsecah_stack_t *ahstack)
1898 {
1899 ipsa_t *newbie, *target;
1900 isaf_t *outbound, *inbound;
1901 int rc, diagnostic;
1902 sadb_sa_t *assoc;
1903 keysock_out_t *kso;
1904 uint32_t newspi;
1905
1906 /*
1907 * Randomly generate a proposed SPI value.
1908 */
1909 if (cl_inet_getspi != NULL) {
1910 cl_inet_getspi(ahstack->ipsecah_netstack->netstack_stackid,
1911 IPPROTO_AH, (uint8_t *)&newspi, sizeof (uint32_t), NULL);
|
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright (c) 2012 Nexenta Systems, Inc. All rights reserved.
25 */
26
27 #include <sys/types.h>
28 #include <sys/stream.h>
29 #include <sys/stropts.h>
30 #include <sys/errno.h>
31 #include <sys/strlog.h>
32 #include <sys/tihdr.h>
33 #include <sys/socket.h>
34 #include <sys/ddi.h>
35 #include <sys/sunddi.h>
36 #include <sys/mkdev.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>
79 * ipsecah_g_nd in ipsecah_init_nd.
80 * All of these are alterable, within the min/max values given, at run time.
81 */
82 static ipsecahparam_t lcl_param_arr[] = {
83 /* min max value name */
84 { 0, 3, 0, "ipsecah_debug"},
85 { 125, 32000, SADB_AGE_INTERVAL_DEFAULT, "ipsecah_age_interval"},
86 { 1, 10, 1, "ipsecah_reap_delay"},
87 { 1, SADB_MAX_REPLAY, 64, "ipsecah_replay_size"},
88 { 1, 300, 15, "ipsecah_acquire_timeout"},
89 { 1, 1800, 90, "ipsecah_larval_timeout"},
90 /* Default lifetime values for ACQUIRE messages. */
91 { 0, 0xffffffffU, 0, "ipsecah_default_soft_bytes"},
92 { 0, 0xffffffffU, 0, "ipsecah_default_hard_bytes"},
93 { 0, 0xffffffffU, 24000, "ipsecah_default_soft_addtime"},
94 { 0, 0xffffffffU, 28800, "ipsecah_default_hard_addtime"},
95 { 0, 0xffffffffU, 0, "ipsecah_default_soft_usetime"},
96 { 0, 0xffffffffU, 0, "ipsecah_default_hard_usetime"},
97 { 0, 1, 0, "ipsecah_log_unknown_spi"},
98 };
99
100 #define ah0dbg(a) printf a
101 /* NOTE: != 0 instead of > 0 so lint doesn't complain. */
102 #define ah1dbg(ahstack, a) if (ahstack->ipsecah_debug != 0) printf a
103 #define ah2dbg(ahstack, a) if (ahstack->ipsecah_debug > 1) printf a
104 #define ah3dbg(ahstack, a) if (ahstack->ipsecah_debug > 2) printf a
105
106 /*
107 * XXX This is broken. Padding should be determined dynamically
108 * depending on the ICV size and IP version number so that the
109 * total AH header size is a multiple of 32 bits or 64 bits
110 * for V4 and V6 respectively. For 96bit ICVs we have no problems.
111 * Anything different from that, we need to fix our code.
112 */
113 #define IPV4_PADDING_ALIGN 0x04 /* Multiple of 32 bits */
114 #define IPV6_PADDING_ALIGN 0x04 /* Multiple of 32 bits */
115
116 /*
117 * Helper macro. Avoids a call to msgdsize if there is only one
118 * mblk in the chain.
119 */
120 #define AH_MSGSIZE(mp) ((mp)->b_cont != NULL ? msgdsize(mp) : MBLKL(mp))
121
122
123 static mblk_t *ah_auth_out_done(mblk_t *, ip_xmit_attr_t *, ipsec_crypto_t *);
124 static mblk_t *ah_auth_in_done(mblk_t *, ip_recv_attr_t *, ipsec_crypto_t *);
125 static mblk_t *ah_process_ip_options_v4(mblk_t *, ipsa_t *, int *, uint_t,
126 boolean_t, ipsecah_stack_t *);
127 static mblk_t *ah_process_ip_options_v6(mblk_t *, ipsa_t *, int *, uint_t,
128 boolean_t, ipsecah_stack_t *);
129 static void ah_getspi(mblk_t *, keysock_in_t *, ipsecah_stack_t *);
130 static void ah_inbound_restart(mblk_t *, ip_recv_attr_t *);
131
132 static mblk_t *ah_outbound(mblk_t *, ip_xmit_attr_t *);
133 static void ah_outbound_finish(mblk_t *, ip_xmit_attr_t *);
134
135 static int ipsecah_open(queue_t *, dev_t *, int, int, cred_t *);
136 static int ipsecah_close(queue_t *);
137 static void ipsecah_wput(queue_t *, mblk_t *);
138 static boolean_t ah_register_out(uint32_t, uint32_t, uint_t, ipsecah_stack_t *,
139 cred_t *);
140 static void *ipsecah_stack_init(netstackid_t stackid, netstack_t *ns);
141 static void ipsecah_stack_fini(netstackid_t stackid, void *arg);
142
143 /* Setable in /etc/system */
144 uint32_t ah_hash_size = IPSEC_DEFAULT_HASH_SIZE;
145
146 static taskq_t *ah_taskq;
147
148 static struct module_info info = {
149 5136, "ipsecah", 0, INFPSZ, 65536, 1024
150 };
151
152 static struct qinit rinit = {
153 (pfi_t)putnext, NULL, ipsecah_open, ipsecah_close, NULL, &info,
154 NULL
155 };
156
157 static struct qinit winit = {
216 netstackid_t stackid = (netstackid_t)(uintptr_t)kp->ks_private;
217 netstack_t *ns;
218 ipsec_stack_t *ipss;
219
220 if ((kp == NULL) || (kp->ks_data == NULL))
221 return (EIO);
222
223 if (rw == KSTAT_WRITE)
224 return (EACCES);
225
226 ns = netstack_find_by_stackid(stackid);
227 if (ns == NULL)
228 return (-1);
229 ipss = ns->netstack_ipsec;
230 if (ipss == NULL) {
231 netstack_rele(ns);
232 return (-1);
233 }
234 ekp = (ah_kstats_t *)kp->ks_data;
235
236 rw_enter(&ipss->ipsec_alg_lock, RW_READER);
237 ekp->ah_stat_num_aalgs.value.ui64 = ipss->ipsec_nalgs[IPSEC_ALG_AUTH];
238 rw_exit(&ipss->ipsec_alg_lock);
239
240 netstack_rele(ns);
241 return (0);
242 }
243
244 /*
245 * Don't have to lock ipsec_age_interval, as only one thread will access it at
246 * a time, because I control the one function that does a qtimeout() on
247 * ah_pfkey_q.
248 */
249 static void
250 ah_ager(void *arg)
251 {
252 ipsecah_stack_t *ahstack = (ipsecah_stack_t *)arg;
253 netstack_t *ns = ahstack->ipsecah_netstack;
254 hrtime_t begin = gethrtime();
255
256 sadb_ager(&ahstack->ah_sadb.s_v4, ahstack->ah_pfkey_q,
257 ahstack->ipsecah_reap_delay, ns);
258 sadb_ager(&ahstack->ah_sadb.s_v6, ahstack->ah_pfkey_q,
388 */
389 static void *
390 ipsecah_stack_init(netstackid_t stackid, netstack_t *ns)
391 {
392 ipsecah_stack_t *ahstack;
393 ipsecahparam_t *ahp;
394
395 ahstack = (ipsecah_stack_t *)kmem_zalloc(sizeof (*ahstack), KM_SLEEP);
396 ahstack->ipsecah_netstack = ns;
397
398 ahp = (ipsecahparam_t *)kmem_alloc(sizeof (lcl_param_arr), KM_SLEEP);
399 ahstack->ipsecah_params = ahp;
400 bcopy(lcl_param_arr, ahp, sizeof (lcl_param_arr));
401
402 (void) ipsecah_param_register(&ahstack->ipsecah_g_nd, ahp,
403 A_CNT(lcl_param_arr));
404
405 (void) ah_kstat_init(ahstack, stackid);
406
407 ahstack->ah_sadb.s_acquire_timeout = &ahstack->ipsecah_acquire_timeout;
408 sadbp_init("AH", &ahstack->ah_sadb, SADB_SATYPE_AH, ah_hash_size,
409 ahstack->ipsecah_netstack);
410
411 mutex_init(&ahstack->ipsecah_param_lock, NULL, MUTEX_DEFAULT, 0);
412
413 ip_drop_register(&ahstack->ah_dropper, "IPsec AH");
414 return (ahstack);
415 }
416
417 /*
418 * Destroy things for AH at module unload time.
419 */
420 void
421 ipsecah_ddi_destroy(void)
422 {
423 netstack_unregister(NS_IPSECAH);
424 taskq_destroy(ah_taskq);
425 }
426
427 /*
428 * Destroy things for AH for one stack... Never called?
429 */
430 static void
431 ipsecah_stack_fini(netstackid_t stackid, void *arg)
432 {
433 ipsecah_stack_t *ahstack = (ipsecah_stack_t *)arg;
434
435 if (ahstack->ah_pfkey_q != NULL) {
436 (void) quntimeout(ahstack->ah_pfkey_q, ahstack->ah_event);
437 }
438 ahstack->ah_sadb.s_acquire_timeout = NULL;
439 sadbp_destroy(&ahstack->ah_sadb, ahstack->ipsecah_netstack);
440 ip_drop_unregister(&ahstack->ah_dropper);
441 mutex_destroy(&ahstack->ipsecah_param_lock);
442 nd_free(&ahstack->ipsecah_g_nd);
443
444 kmem_free(ahstack->ipsecah_params, sizeof (lcl_param_arr));
445 ahstack->ipsecah_params = NULL;
446 kstat_delete_netstack(ahstack->ah_ksp, stackid);
447 ahstack->ah_ksp = NULL;
448 ahstack->ah_kstats = NULL;
449
450 kmem_free(ahstack, sizeof (*ahstack));
451 }
452
453 /*
454 * AH module open routine, which is here for keysock plumbing.
455 * Keysock is pushed over {AH,ESP} which is an artifact from the Bad Old
456 * Days of export control, and fears that ESP would not be allowed
457 * to be shipped at all by default. Eventually, keysock should
540 mp = sadb_keysock_out(serial);
541 if (mp == NULL) {
542 ah0dbg(("ah_register_out: couldn't allocate mblk.\n"));
543 return (B_FALSE);
544 }
545
546 if (is_system_labeled() && (cr != NULL)) {
547 sens_tsl = crgetlabel(cr);
548 if (sens_tsl != NULL) {
549 sens_len = sadb_sens_len_from_label(sens_tsl);
550 allocsize += sens_len;
551 }
552 }
553
554 /*
555 * Allocate the PF_KEY message that follows KEYSOCK_OUT.
556 * The alg reader lock needs to be held while allocating
557 * the variable part (i.e. the algorithms) of the message.
558 */
559
560 rw_enter(&ipss->ipsec_alg_lock, RW_READER);
561
562 /*
563 * Return only valid algorithms, so the number of algorithms
564 * to send up may be less than the number of algorithm entries
565 * in the table.
566 */
567 authalgs = ipss->ipsec_alglists[IPSEC_ALG_AUTH];
568 for (num_aalgs = 0, i = 0; i < IPSEC_MAX_ALGS; i++)
569 if (authalgs[i] != NULL && ALG_VALID(authalgs[i]))
570 num_aalgs++;
571
572 /*
573 * Fill SADB_REGISTER message's algorithm descriptors. Hold
574 * down the lock while filling it.
575 */
576 if (num_aalgs != 0) {
577 allocsize += (num_aalgs * sizeof (*saalg));
578 allocsize += sizeof (*sasupp);
579 }
580 mp->b_cont = allocb(allocsize, BPRI_HI);
581 if (mp->b_cont == NULL) {
582 rw_exit(&ipss->ipsec_alg_lock);
583 freemsg(mp);
584 return (B_FALSE);
585 }
586
587 mp->b_cont->b_wptr += allocsize;
588 nextext = (sadb_ext_t *)(mp->b_cont->b_rptr + sizeof (*samsg));
589
590 if (num_aalgs != 0) {
591
592 saalg = (sadb_alg_t *)(((uint8_t *)nextext) + sizeof (*sasupp));
593 ASSERT(((ulong_t)saalg & 0x7) == 0);
594
595 numalgs_snap = 0;
596 for (i = 0;
597 ((i < IPSEC_MAX_ALGS) && (numalgs_snap < num_aalgs));
598 i++) {
599 if (authalgs[i] == NULL || !ALG_VALID(authalgs[i]))
600 continue;
601
602 saalg->sadb_alg_id = authalgs[i]->alg_id;
609 ASSERT(authalgs[i]->alg_saltlen == 0);
610 saalg->sadb_x_alg_saltbits =
611 SADB_8TO1(authalgs[i]->alg_saltlen);
612 numalgs_snap++;
613 saalg++;
614 }
615 ASSERT(numalgs_snap == num_aalgs);
616 #ifdef DEBUG
617 /*
618 * Reality check to make sure I snagged all of the
619 * algorithms.
620 */
621 for (; i < IPSEC_MAX_ALGS; i++)
622 if (authalgs[i] != NULL && ALG_VALID(authalgs[i]))
623 cmn_err(CE_PANIC,
624 "ah_register_out()! Missed #%d.\n", i);
625 #endif /* DEBUG */
626 nextext = (sadb_ext_t *)saalg;
627 }
628
629 rw_exit(&ipss->ipsec_alg_lock);
630
631 if (sens_tsl != NULL) {
632 sens = (sadb_sens_t *)nextext;
633 sadb_sens_from_label(sens, SADB_EXT_SENSITIVITY,
634 sens_tsl, sens_len);
635
636 nextext = (sadb_ext_t *)(((uint8_t *)sens) + sens_len);
637 }
638
639 /* Now fill the restof the SADB_REGISTER message. */
640
641 samsg = (sadb_msg_t *)mp->b_cont->b_rptr;
642 samsg->sadb_msg_version = PF_KEY_V2;
643 samsg->sadb_msg_type = SADB_REGISTER;
644 samsg->sadb_msg_errno = 0;
645 samsg->sadb_msg_satype = SADB_SATYPE_AH;
646 samsg->sadb_msg_len = SADB_8TO64(allocsize);
647 samsg->sadb_msg_reserved = 0;
648 /*
649 * Assume caller has sufficient sequence/pid number info. If it's one
1090 /* Stuff I don't support, for now. XXX Diagnostic? */
1091 if (ksi->ks_in_extv[SADB_EXT_LIFETIME_CURRENT] != NULL)
1092 return (EOPNOTSUPP);
1093
1094 if (ksi->ks_in_extv[SADB_EXT_SENSITIVITY] != NULL) {
1095 if (!is_system_labeled())
1096 return (EOPNOTSUPP);
1097 }
1098
1099 if (ksi->ks_in_extv[SADB_X_EXT_OUTER_SENS] != NULL) {
1100 if (!is_system_labeled())
1101 return (EOPNOTSUPP);
1102 }
1103 /*
1104 * XXX Policy : I'm not checking identities at this time, but
1105 * if I did, I'd do them here, before I sent the weak key
1106 * check up to the algorithm.
1107 */
1108
1109 /* verify that there is a mapping for the specified algorithm */
1110 rw_enter(&ipss->ipsec_alg_lock, RW_READER);
1111 aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH][assoc->sadb_sa_auth];
1112 if (aalg == NULL || !ALG_VALID(aalg)) {
1113 rw_exit(&ipss->ipsec_alg_lock);
1114 ah1dbg(ahstack, ("Couldn't find auth alg #%d.\n",
1115 assoc->sadb_sa_auth));
1116 *diagnostic = SADB_X_DIAGNOSTIC_BAD_AALG;
1117 return (EINVAL);
1118 }
1119 ASSERT(aalg->alg_mech_type != CRYPTO_MECHANISM_INVALID);
1120
1121 /* sanity check key sizes */
1122 if (!ipsec_valid_key_size(key->sadb_key_bits, aalg)) {
1123 rw_exit(&ipss->ipsec_alg_lock);
1124 *diagnostic = SADB_X_DIAGNOSTIC_BAD_AKEYBITS;
1125 return (EINVAL);
1126 }
1127
1128 /* check key and fix parity if needed */
1129 if (ipsec_check_key(aalg->alg_mech_type, key, B_TRUE,
1130 diagnostic) != 0) {
1131 rw_exit(&ipss->ipsec_alg_lock);
1132 return (EINVAL);
1133 }
1134
1135 rw_exit(&ipss->ipsec_alg_lock);
1136
1137 return (ah_add_sa_finish(mp, (sadb_msg_t *)mp->b_cont->b_rptr, ksi,
1138 diagnostic, ahstack));
1139 }
1140
1141 /* Refactor me */
1142 /*
1143 * Update a security association. Updates come in two varieties. The first
1144 * is an update of lifetimes on a non-larval SA. The second is an update of
1145 * a larval SA, which ends up looking a lot more like an add.
1146 */
1147 static int
1148 ah_update_sa(mblk_t *mp, keysock_in_t *ksi, int *diagnostic,
1149 ipsecah_stack_t *ahstack, uint8_t sadb_msg_type)
1150 {
1151 sadb_sa_t *assoc = (sadb_sa_t *)ksi->ks_in_extv[SADB_EXT_SA];
1152 sadb_address_t *dstext =
1153 (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_DST];
1154 mblk_t *buf_pkt;
1155 int rcode;
1702 }
1703
1704 inrc = sadb_age_bytes(ahstack->ah_pfkey_q, inassoc, bytes, B_TRUE);
1705 outrc = sadb_age_bytes(ahstack->ah_pfkey_q, outassoc, bytes, B_FALSE);
1706
1707 /*
1708 * REFRELE any peer SA.
1709 *
1710 * Because of the multi-line macro nature of IPSA_REFRELE, keep
1711 * them in { }.
1712 */
1713 if (inbound) {
1714 IPSA_REFRELE(outassoc);
1715 } else {
1716 IPSA_REFRELE(inassoc);
1717 }
1718
1719 return (inrc && outrc);
1720 }
1721
1722 /* Refactor me */
1723 /*
1724 * Handle the SADB_GETSPI message. Create a larval SA.
1725 */
1726 static void
1727 ah_getspi(mblk_t *mp, keysock_in_t *ksi, ipsecah_stack_t *ahstack)
1728 {
1729 ipsa_t *newbie, *target;
1730 isaf_t *outbound, *inbound;
1731 int rc, diagnostic;
1732 sadb_sa_t *assoc;
1733 keysock_out_t *kso;
1734 uint32_t newspi;
1735
1736 /*
1737 * Randomly generate a proposed SPI value.
1738 */
1739 if (cl_inet_getspi != NULL) {
1740 cl_inet_getspi(ahstack->ipsecah_netstack->netstack_stackid,
1741 IPPROTO_AH, (uint8_t *)&newspi, sizeof (uint32_t), NULL);
|