xref: /illumos-gate/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_dhchap.c (revision 33efde4275d24731ef87927237b0ffb0630b6b2d)
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
9  * http://www.opensource.org/licenses/cddl1.txt.
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 /*
23  * Copyright (c) 2004-2011 Emulex. All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <emlxs.h>
28 
29 #ifdef DHCHAP_SUPPORT
30 
31 #include <md5.h>
32 #include <sha1.h>
33 #include <sys/sha1_consts.h>
34 #include <bignum.h>
35 #include <sys/time.h>
36 
37 
38 #define	RAND
39 
40 #ifndef ENABLE
41 #define	ENABLE   1
42 #endif	/* ENABLE */
43 
44 #ifndef DISABLE
45 #define	DISABLE   0
46 #endif	/* DISABLE */
47 
48 
49 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
50 EMLXS_MSG_DEF(EMLXS_DHCHAP_C);
51 
52 static char *emlxs_dhc_pstate_xlate(uint32_t state);
53 static char *emlxs_dhc_nstate_xlate(uint32_t state);
54 static uint32_t emlxs_check_dhgp(emlxs_port_t *port, NODELIST *ndlp,
55 	uint32_t *dh_id, uint16_t cnt, uint32_t *dhgp_id);
56 static void emlxs_dhc_set_reauth_time(emlxs_port_t *port,
57 	emlxs_node_t *ndlp, uint32_t status);
58 
59 static void emlxs_auth_cfg_init(emlxs_hba_t *hba);
60 static void emlxs_auth_cfg_fini(emlxs_hba_t *hba);
61 static void emlxs_auth_cfg_read(emlxs_hba_t *hba);
62 static uint32_t emlxs_auth_cfg_parse(emlxs_hba_t *hba,
63 	emlxs_auth_cfg_t *config, char *prop_str);
64 static emlxs_auth_cfg_t *emlxs_auth_cfg_get(emlxs_hba_t *hba,
65 	uint8_t *lwwpn, uint8_t *rwwpn);
66 static emlxs_auth_cfg_t *emlxs_auth_cfg_create(emlxs_hba_t *hba,
67 	uint8_t *lwwpn, uint8_t *rwwpn);
68 static void emlxs_auth_cfg_destroy(emlxs_hba_t *hba,
69 	emlxs_auth_cfg_t *auth_cfg);
70 static void emlxs_auth_cfg_print(emlxs_hba_t *hba,
71 	emlxs_auth_cfg_t *auth_cfg);
72 
73 static void emlxs_auth_key_init(emlxs_hba_t *hba);
74 static void emlxs_auth_key_fini(emlxs_hba_t *hba);
75 static void emlxs_auth_key_read(emlxs_hba_t *hba);
76 static uint32_t emlxs_auth_key_parse(emlxs_hba_t *hba,
77 	emlxs_auth_key_t *auth_key, char *prop_str);
78 static emlxs_auth_key_t *emlxs_auth_key_get(emlxs_hba_t *hba,
79 	uint8_t *lwwpn, uint8_t *rwwpn);
80 static emlxs_auth_key_t *emlxs_auth_key_create(emlxs_hba_t *hba,
81 	uint8_t *lwwpn, uint8_t *rwwpn);
82 static void emlxs_auth_key_destroy(emlxs_hba_t *hba,
83 	emlxs_auth_key_t *auth_key);
84 static void emlxs_auth_key_print(emlxs_hba_t *hba,
85 	emlxs_auth_key_t *auth_key);
86 
87 static void emlxs_get_random_bytes(NODELIST *ndlp, uint8_t *rdn,
88 	uint32_t len);
89 static emlxs_auth_cfg_t *emlxs_auth_cfg_find(emlxs_port_t *port,
90 	uint8_t *rwwpn);
91 static emlxs_auth_key_t *emlxs_auth_key_find(emlxs_port_t *port,
92 	uint8_t *rwwpn);
93 static void emlxs_dhc_auth_complete(emlxs_port_t *port,
94 	emlxs_node_t *ndlp, uint32_t status);
95 static void emlxs_log_auth_event(emlxs_port_t *port, NODELIST *ndlp,
96 	char *subclass, char *info);
97 static int emlxs_issue_auth_negotiate(emlxs_port_t *port,
98 	emlxs_node_t *ndlp, uint8_t retry);
99 static void emlxs_cmpl_auth_negotiate_issue(fc_packet_t *pkt);
100 static uint32_t *emlxs_hash_rsp(emlxs_port_t *port,
101 	emlxs_port_dhc_t *port_dhc, NODELIST *ndlp, uint32_t tran_id,
102 	union challenge_val un_cval, uint8_t *dhval, uint32_t dhvallen);
103 static fc_packet_t *emlxs_prep_els_fc_pkt(emlxs_port_t *port,
104 	uint32_t d_id, uint32_t cmd_size, uint32_t rsp_size,
105 	uint32_t datalen, int32_t sleepflag);
106 
107 static uint32_t *emlxs_hash_vrf(emlxs_port_t *port,
108 	emlxs_port_dhc_t *port_dhc, NODELIST *ndlp, uint32_t tran_id,
109 	union challenge_val un_cval);
110 
111 
112 static BIG_ERR_CODE
113 emlxs_interm_hash(emlxs_port_t *port, emlxs_port_dhc_t *port_dhc,
114 	NODELIST *ndlp, void *hash_val, uint32_t tran_id,
115 	union challenge_val un_cval, uint8_t *dhval, uint32_t *);
116 
117 static BIG_ERR_CODE
118 emlxs_BIGNUM_get_pubkey(emlxs_port_t *port, emlxs_port_dhc_t *port_dhc,
119 	NODELIST *ndlp, uint8_t *dhval, uint32_t *dhvallen,
120 	uint32_t hash_size, uint32_t dhgp_id);
121 static BIG_ERR_CODE
122 emlxs_BIGNUM_get_dhval(emlxs_port_t *port, emlxs_port_dhc_t *port_dhc,
123 	NODELIST *ndlp, uint8_t *dhval, uint32_t *dhval_len,
124 	uint32_t dhgp_id, uint8_t *priv_key, uint32_t privkey_len);
125 static uint32_t *
126 emlxs_hash_verification(emlxs_port_t *port, emlxs_port_dhc_t *port_dhc,
127 	NODELIST *ndlp, uint32_t tran_id, uint8_t *dhval,
128 	uint32_t dhval_len, uint32_t flag, uint8_t *bi_cval);
129 
130 static uint32_t *
131 emlxs_hash_get_R2(emlxs_port_t *port, emlxs_port_dhc_t *port_dhc,
132 	NODELIST *ndlp, uint32_t tran_id, uint8_t *dhval,
133 	uint32_t dhval_len, uint32_t flag, uint8_t *bi_cval);
134 
135 static uint32_t emlxs_issue_auth_reject(emlxs_port_t *port,
136 	NODELIST *ndlp, int retry, uint32_t *arg, uint8_t ReasonCode,
137 	uint8_t ReasonCodeExplanation);
138 
139 static uint32_t emlxs_disc_neverdev(emlxs_port_t *port, void *arg1,
140 	void *arg2, void *arg3, void *arg4, uint32_t evt);
141 static uint32_t emlxs_rcv_auth_msg_unmapped_node(emlxs_port_t *port,
142 	void *arg1, void *arg2, void *arg3, void *arg4, uint32_t evt);
143 static uint32_t emlxs_rcv_auth_msg_npr_node(emlxs_port_t *port,
144 	void *arg1, void *arg2, void *arg3, void *arg4, uint32_t evt);
145 static uint32_t emlxs_cmpl_auth_msg_npr_node(emlxs_port_t *port,
146 	void *arg1, void *arg2, void *arg3, void *arg4, uint32_t evt);
147 static uint32_t emlxs_rcv_auth_msg_auth_negotiate_issue(emlxs_port_t *port,
148 	void *arg1, void *arg2, void *arg3, void *arg4, uint32_t evt);
149 static uint32_t emlxs_cmpl_auth_msg_auth_negotiate_issue(emlxs_port_t *port,
150 	void *arg1, void *arg2, void *arg3, void *arg4, uint32_t evt);
151 static uint32_t emlxs_rcv_auth_msg_auth_negotiate_rcv(emlxs_port_t *port,
152 	void *arg1, void *arg2, void *arg3, void *arg4, uint32_t evt);
153 static uint32_t emlxs_cmpl_auth_msg_auth_negotiate_rcv(emlxs_port_t *port,
154 	void *arg1, void *arg2, void *arg3, void *arg4, uint32_t evt);
155 static uint32_t
156 emlxs_rcv_auth_msg_auth_negotiate_cmpl_wait4next(emlxs_port_t *port,
157 	void *arg1, void *arg2, void *arg3, void *arg4, uint32_t evt);
158 static uint32_t
159 emlxs_cmpl_auth_msg_auth_negotiate_cmpl_wait4next(emlxs_port_t *port,
160 	void *arg1, void *arg2, void *arg3, void *arg4, uint32_t evt);
161 static uint32_t
162 emlxs_rcv_auth_msg_dhchap_challenge_issue(emlxs_port_t *port, void *arg1,
163 	void *arg2, void *arg3, void *arg4, uint32_t evt);
164 static uint32_t
165 emlxs_cmpl_auth_msg_dhchap_challenge_issue(emlxs_port_t *port, void *arg1,
166 	void *arg2, void *arg3, void *arg4, uint32_t evt);
167 static uint32_t emlxs_rcv_auth_msg_dhchap_reply_issue(emlxs_port_t *port,
168 	void *arg1, void *arg2, void *arg3, void *arg4, uint32_t evt);
169 static uint32_t emlxs_cmpl_auth_msg_dhchap_reply_issue(emlxs_port_t *port,
170 	void *arg1, void *arg2, void *arg3, void *arg4, uint32_t evt);
171 static uint32_t
172 emlxs_rcv_auth_msg_dhchap_challenge_cmpl_wait4next(emlxs_port_t *port,
173 	void *arg1, void *arg2, void *arg3, void *arg4, uint32_t evt);
174 static uint32_t
175 emlxs_cmpl_auth_msg_dhchap_challenge_cmpl_wait4next(emlxs_port_t *port,
176 	void *arg1, void *arg2, void *arg3, void *arg4, uint32_t evt);
177 static uint32_t
178 emlxs_rcv_auth_msg_dhchap_reply_cmpl_wait4next(emlxs_port_t *port,
179 	void *arg1, void *arg2, void *arg3, void *arg4, uint32_t evt);
180 static uint32_t
181 emlxs_cmpl_auth_msg_dhchap_reply_cmpl_wait4next(emlxs_port_t *port,
182 	void *arg1, void *arg2, void *arg3, void *arg4, uint32_t evt);
183 static uint32_t emlxs_rcv_auth_msg_dhchap_success_issue(emlxs_port_t *port,
184 	void *arg1, void *arg2, void *arg3, void *arg4, uint32_t evt);
185 static uint32_t
186 emlxs_cmpl_auth_msg_dhchap_success_issue(emlxs_port_t *port, void *arg1,
187 	void *arg2, void *arg3, void *arg4, uint32_t evt);
188 static uint32_t
189 emlxs_rcv_auth_msg_dhchap_success_issue_wait4next(emlxs_port_t *port,
190 	void *arg1, void *arg2, void *arg3, void *arg4, uint32_t evt);
191 static uint32_t
192 emlxs_cmpl_auth_msg_dhchap_success_issue_wait4next(emlxs_port_t *port,
193 	void *arg1, void *arg2, void *arg3, void *arg4, uint32_t evt);
194 static uint32_t
195 emlxs_rcv_auth_msg_dhchap_success_cmpl_wait4next(emlxs_port_t *port,
196 	void *arg1, void *arg2, void *arg3, void *arg4, uint32_t evt);
197 static uint32_t
198 emlxs_cmpl_auth_msg_dhchap_success_cmpl_wait4next(emlxs_port_t *port,
199 	void *arg1, void *arg2, void *arg3, void *arg4, uint32_t evt);
200 
201 
202 static uint32_t emlxs_device_recov_unmapped_node(emlxs_port_t *port,
203 	void *arg1, void *arg2, void *arg3, void *arg4, uint32_t evt);
204 static uint32_t emlxs_device_rm_npr_node(emlxs_port_t *port, void *arg1,
205 	void *arg2, void *arg3, void *arg4, uint32_t evt);
206 static uint32_t emlxs_device_recov_npr_node(emlxs_port_t *port, void *arg1,
207 	void *arg2, void *arg3, void *arg4, uint32_t evt);
208 static uint32_t emlxs_device_rem_auth(emlxs_port_t *port, void *arg1,
209 	void *arg2, void *arg3, void *arg4, uint32_t evt);
210 static uint32_t emlxs_device_recov_auth(emlxs_port_t *port, void *arg1,
211 	void *arg2, void *arg3, void *arg4, uint32_t evt);
212 
213 static uint8_t emlxs_null_wwn[8] =
214 	{0, 0, 0, 0, 0, 0, 0, 0};
215 static uint8_t emlxs_fabric_wwn[8] =
216 	{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
217 
218 unsigned char dhgp1_pVal[] =
219 {0xEE, 0xAF, 0x0A, 0xB9, 0xAD, 0xB3, 0x8D, 0xD6, 0x9C, 0x33, 0xF8, 0x0A, 0xFA,
220 0x8F, 0xC5, 0xE8,
221 0x60, 0x72, 0x61, 0x87, 0x75, 0xFF, 0x3C, 0x0B, 0x9E, 0xA2, 0x31, 0x4C, 0x9C,
222 0x25, 0x65, 0x76,
223 0xD6, 0x74, 0xDF, 0x74, 0x96, 0xEA, 0x81, 0xD3, 0x38, 0x3B, 0x48, 0x13, 0xD6,
224 0x92, 0xC6, 0xE0,
225 0xE0, 0xD5, 0xD8, 0xE2, 0x50, 0xB9, 0x8B, 0xE4, 0x8E, 0x49, 0x5C, 0x1D, 0x60,
226 0x89, 0xDA, 0xD1,
227 0x5D, 0xC7, 0xD7, 0xB4, 0x61, 0x54, 0xD6, 0xB6, 0xCE, 0x8E, 0xF4, 0xAD, 0x69,
228 0xB1, 0x5D, 0x49,
229 0x82, 0x55, 0x9B, 0x29, 0x7B, 0xCF, 0x18, 0x85, 0xC5, 0x29, 0xF5, 0x66, 0x66,
230 0x0E, 0x57, 0xEC,
231 0x68, 0xED, 0xBC, 0x3C, 0x05, 0x72, 0x6C, 0xC0, 0x2F, 0xD4, 0xCB, 0xF4, 0x97,
232 0x6E, 0xAA, 0x9A,
233 0xFD, 0x51, 0x38, 0xFE, 0x83, 0x76, 0x43, 0x5B, 0x9F, 0xC6, 0x1D, 0x2F, 0xC0,
234 0xEB, 0x06, 0xE3,
235 };
236 
237 unsigned char dhgp2_pVal[] =
238 {0xD7, 0x79, 0x46, 0x82, 0x6E, 0x81, 0x19, 0x14, 0xB3, 0x94, 0x01, 0xD5, 0x6A,
239 0x0A, 0x78, 0x43,
240 0xA8, 0xE7, 0x57, 0x5D, 0x73, 0x8C, 0x67, 0x2A, 0x09, 0x0A, 0xB1, 0x18, 0x7D,
241 0x69, 0x0D, 0xC4,
242 0x38, 0x72, 0xFC, 0x06, 0xA7, 0xB6, 0xA4, 0x3F, 0x3B, 0x95, 0xBE, 0xAE, 0xC7,
243 0xDF, 0x04, 0xB9,
244 0xD2, 0x42, 0xEB, 0xDC, 0x48, 0x11, 0x11, 0x28, 0x32, 0x16, 0xCE, 0x81, 0x6E,
245 0x00, 0x4B, 0x78,
246 0x6C, 0x5F, 0xCE, 0x85, 0x67, 0x80, 0xD4, 0x18, 0x37, 0xD9, 0x5A, 0xD7, 0x87,
247 0xA5, 0x0B, 0xBE,
248 0x90, 0xBD, 0x3A, 0x9C, 0x98, 0xAC, 0x0F, 0x5F, 0xC0, 0xDE, 0x74, 0x4B, 0x1C,
249 0xDE, 0x18, 0x91,
250 0x69, 0x08, 0x94, 0xBC, 0x1F, 0x65, 0xE0, 0x0D, 0xE1, 0x5B, 0x4B, 0x2A, 0xA6,
251 0xD8, 0x71, 0x00,
252 0xC9, 0xEC, 0xC2, 0x52, 0x7E, 0x45, 0xEB, 0x84, 0x9D, 0xEB, 0x14, 0xBB, 0x20,
253 0x49, 0xB1, 0x63,
254 0xEA, 0x04, 0x18, 0x7F, 0xD2, 0x7C, 0x1B, 0xD9, 0xC7, 0x95, 0x8C, 0xD4, 0x0C,
255 0xE7, 0x06, 0x7A,
256 0x9C, 0x02, 0x4F, 0x9B, 0x7C, 0x5A, 0x0B, 0x4F, 0x50, 0x03, 0x68, 0x61, 0x61,
257 0xF0, 0x60, 0x5B
258 };
259 
260 unsigned char dhgp3_pVal[] =
261 {0x9D, 0xEF, 0x3C, 0xAF, 0xB9, 0x39, 0x27, 0x7A, 0xB1, 0xF1, 0x2A, 0x86, 0x17,
262 0xA4, 0x7B, 0xBB,
263 0xDB, 0xA5, 0x1D, 0xF4, 0x99, 0xAC, 0x4C, 0x80, 0xBE, 0xEE, 0xA9, 0x61, 0x4B,
264 0x19, 0xCC, 0x4D,
265 0x5F, 0x4F, 0x5F, 0x55, 0x6E, 0x27, 0xCB, 0xDE, 0x51, 0xC6, 0xA9, 0x4B, 0xE4,
266 0x60, 0x7A, 0x29,
267 0x15, 0x58, 0x90, 0x3B, 0xA0, 0xD0, 0xF8, 0x43, 0x80, 0xB6, 0x55, 0xBB, 0x9A,
268 0x22, 0xE8, 0xDC,
269 0xDF, 0x02, 0x8A, 0x7C, 0xEC, 0x67, 0xF0, 0xD0, 0x81, 0x34, 0xB1, 0xC8, 0xB9,
270 0x79, 0x89, 0x14,
271 0x9B, 0x60, 0x9E, 0x0B, 0xE3, 0xBA, 0xB6, 0x3D, 0x47, 0x54, 0x83, 0x81, 0xDB,
272 0xC5, 0xB1, 0xFC,
273 0x76, 0x4E, 0x3F, 0x4B, 0x53, 0xDD, 0x9D, 0xA1, 0x15, 0x8B, 0xFD, 0x3E, 0x2B,
274 0x9C, 0x8C, 0xF5,
275 0x6E, 0xDF, 0x01, 0x95, 0x39, 0x34, 0x96, 0x27, 0xDB, 0x2F, 0xD5, 0x3D, 0x24,
276 0xB7, 0xC4, 0x86,
277 0x65, 0x77, 0x2E, 0x43, 0x7D, 0x6C, 0x7F, 0x8C, 0xE4, 0x42, 0x73, 0x4A, 0xF7,
278 0xCC, 0xB7, 0xAE,
279 0x83, 0x7C, 0x26, 0x4A, 0xE3, 0xA9, 0xBE, 0xB8, 0x7F, 0x8A, 0x2F, 0xE9, 0xB8,
280 0xB5, 0x29, 0x2E,
281 0x5A, 0x02, 0x1F, 0xFF, 0x5E, 0x91, 0x47, 0x9E, 0x8C, 0xE7, 0xA2, 0x8C, 0x24,
282 0x42, 0xC6, 0xF3,
283 0x15, 0x18, 0x0F, 0x93, 0x49, 0x9A, 0x23, 0x4D, 0xCF, 0x76, 0xE3, 0xFE, 0xD1,
284 0x35, 0xF9, 0xBB
285 };
286 
287 unsigned char dhgp4_pVal[] =
288 {0xAC, 0x6B, 0xDB, 0x41, 0x32, 0x4A, 0x9A, 0x9B, 0xF1, 0x66, 0xDE, 0x5E, 0x13,
289 0x89, 0x58, 0x2F,
290 0xAF, 0x72, 0xB6, 0x65, 0x19, 0x87, 0xEE, 0x07, 0xFC, 0x31, 0x92, 0x94, 0x3D,
291 0xB5, 0x60, 0x50,
292 0xA3, 0x73, 0x29, 0xCB, 0xB4, 0xA0, 0x99, 0xED, 0x81, 0x93, 0xE0, 0x75, 0x77,
293 0x67, 0xA1, 0x3D,
294 0xD5, 0x23, 0x12, 0xAB, 0x4B, 0x03, 0x31, 0x0D, 0xCD, 0x7F, 0x48, 0xA9, 0xDA,
295 0x04, 0xFD, 0x50,
296 0xE8, 0x08, 0x39, 0x69, 0xED, 0xB7, 0x67, 0xB0, 0xCF, 0x60, 0x95, 0x17, 0x9A,
297 0x16, 0x3A, 0xB3,
298 0x66, 0x1A, 0x05, 0xFB, 0xD5, 0xFA, 0xAA, 0xE8, 0x29, 0x18, 0xA9, 0x96, 0x2F,
299 0x0B, 0x93, 0xB8,
300 0x55, 0xF9, 0x79, 0x93, 0xEC, 0x97, 0x5E, 0xEA, 0xA8, 0x0D, 0x74, 0x0A, 0xDB,
301 0xF4, 0xFF, 0x74,
302 0x73, 0x59, 0xD0, 0x41, 0xD5, 0xC3, 0x3E, 0xA7, 0x1D, 0x28, 0x1E, 0x44, 0x6B,
303 0x14, 0x77, 0x3B,
304 0xCA, 0x97, 0xB4, 0x3A, 0x23, 0xFB, 0x80, 0x16, 0x76, 0xBD, 0x20, 0x7A, 0x43,
305 0x6C, 0x64, 0x81,
306 0xF1, 0xD2, 0xB9, 0x07, 0x87, 0x17, 0x46, 0x1A, 0x5B, 0x9D, 0x32, 0xE6, 0x88,
307 0xF8, 0x77, 0x48,
308 0x54, 0x45, 0x23, 0xB5, 0x24, 0xB0, 0xD5, 0x7D, 0x5E, 0xA7, 0x7A, 0x27, 0x75,
309 0xD2, 0xEC, 0xFA,
310 0x03, 0x2C, 0xFB, 0xDB, 0xF5, 0x2F, 0xB3, 0x78, 0x61, 0x60, 0x27, 0x90, 0x04,
311 0xE5, 0x7A, 0xE6,
312 0xAF, 0x87, 0x4E, 0x73, 0x03, 0xCE, 0x53, 0x29, 0x9C, 0xCC, 0x04, 0x1C, 0x7B,
313 0xC3, 0x08, 0xD8,
314 0x2A, 0x56, 0x98, 0xF3, 0xA8, 0xD0, 0xC3, 0x82, 0x71, 0xAE, 0x35, 0xF8, 0xE9,
315 0xDB, 0xFB, 0xB6,
316 0x94, 0xB5, 0xC8, 0x03, 0xD8, 0x9F, 0x7A, 0xE4, 0x35, 0xDE, 0x23, 0x6D, 0x52,
317 0x5F, 0x54, 0x75,
318 0x9B, 0x65, 0xE3, 0x72, 0xFC, 0xD6, 0x8E, 0xF2, 0x0F, 0xA7, 0x11, 0x1F, 0x9E,
319 0x4A, 0xFF, 0x73
320 };
321 
322 /*
323  * myrand is used for test only, eventually it should be replaced by the random
324  * number. AND it is basically the private key.
325  */
326 /* #define	MYRAND */
327 #ifdef MYRAND
328 unsigned char myrand[] =
329 {0x11, 0x11, 0x22, 0x22,
330 	0x33, 0x33, 0x44, 0x44,
331 	0x55, 0x55, 0x66, 0x66,
332 	0x77, 0x77, 0x88, 0x88,
333 0x99, 0x99, 0x00, 0x00};
334 #endif	/* MYRAND */
335 
336 
337 
338 
339 /* Node Events */
340 #define	NODE_EVENT_DEVICE_RM	0x0 /* Auth response timeout & fail */
341 #define	NODE_EVENT_DEVICE_RECOVERY 0x1 /* Auth response timeout & recovery */
342 #define	NODE_EVENT_RCV_AUTH_MSG	 0x2 /* Unsolicited Auth received */
343 #define	NODE_EVENT_CMPL_AUTH_MSG 0x3
344 #define	NODE_EVENT_MAX_EVENT	 0x4
345 
346 emlxs_table_t emlxs_event_table[] =
347 {
348 	{NODE_EVENT_DEVICE_RM, "DEVICE_REMOVE"},
349 	{NODE_EVENT_DEVICE_RECOVERY, "DEVICE_RECOVERY"},
350 	{NODE_EVENT_RCV_AUTH_MSG, "AUTH_MSG_RCVD"},
351 	{NODE_EVENT_CMPL_AUTH_MSG, "AUTH_MSG_CMPL"},
352 
353 };	/* emlxs_event_table() */
354 
355 emlxs_table_t emlxs_pstate_table[] =
356 {
357 	{ELX_FABRIC_STATE_UNKNOWN, "FABRIC_STATE_UNKNOWN"},
358 	{ELX_FABRIC_AUTH_DISABLED, "FABRIC_AUTH_DISABLED"},
359 	{ELX_FABRIC_AUTH_FAILED, "FABRIC_AUTH_FAILED"},
360 	{ELX_FABRIC_AUTH_SUCCESS, "FABRIC_AUTH_SUCCESS"},
361 	{ELX_FABRIC_IN_AUTH, "FABRIC_IN_AUTH"},
362 	{ELX_FABRIC_IN_REAUTH, "FABRIC_IN_REAUTH"},
363 
364 };	/* emlxs_pstate_table() */
365 
366 emlxs_table_t emlxs_nstate_table[] =
367 {
368 {NODE_STATE_UNKNOWN, "STATE_UNKNOWN"},
369 {NODE_STATE_AUTH_DISABLED, "AUTH_DISABLED"},
370 {NODE_STATE_AUTH_FAILED, "AUTH_FAILED"},
371 {NODE_STATE_AUTH_SUCCESS, "AUTH_SUCCESS"},
372 {NODE_STATE_AUTH_NEGOTIATE_ISSUE, "NEGOTIATE_ISSUE"},
373 {NODE_STATE_AUTH_NEGOTIATE_RCV, "NEGOTIATE_RCV"},
374 {NODE_STATE_AUTH_NEGOTIATE_CMPL_WAIT4NEXT, "NEGOTIATE_CMPL"},
375 {NODE_STATE_DHCHAP_CHALLENGE_ISSUE, "DHCHAP_CHALLENGE_ISSUE"},
376 {NODE_STATE_DHCHAP_REPLY_ISSUE, "DHCHAP_REPLY_ISSUE"},
377 {NODE_STATE_DHCHAP_CHALLENGE_CMPL_WAIT4NEXT, "DHCHAP_CHALLENGE_CMPL"},
378 {NODE_STATE_DHCHAP_REPLY_CMPL_WAIT4NEXT, "DHCHAP_REPLY_CMPL"},
379 {NODE_STATE_DHCHAP_SUCCESS_ISSUE, "DHCHAP_SUCCESS_ISSUE"},
380 {NODE_STATE_DHCHAP_SUCCESS_ISSUE_WAIT4NEXT, "DHCHAP_SUCCESS_ISSUE_WAIT"},
381 {NODE_STATE_DHCHAP_SUCCESS_CMPL_WAIT4NEXT, "DHCHAP_SUCCESS_CMPL"},
382 };	/* emlxs_nstate_table() */
383 
384 extern char *
emlxs_dhc_event_xlate(uint32_t state)385 emlxs_dhc_event_xlate(uint32_t state)
386 {
387 	static char buffer[32];
388 	uint32_t i;
389 	uint32_t count;
390 
391 	count = sizeof (emlxs_event_table) / sizeof (emlxs_table_t);
392 	for (i = 0; i < count; i++) {
393 		if (state == emlxs_event_table[i].code) {
394 			return (emlxs_event_table[i].string);
395 		}
396 	}
397 
398 	(void) snprintf(buffer, sizeof (buffer), "event=0x%x", state);
399 	return (buffer);
400 
401 } /* emlxs_dhc_event_xlate() */
402 
403 
404 extern void
emlxs_dhc_state(emlxs_port_t * port,emlxs_node_t * ndlp,uint32_t state,uint32_t reason,uint32_t explaination)405 emlxs_dhc_state(emlxs_port_t *port, emlxs_node_t *ndlp, uint32_t state,
406 	uint32_t reason, uint32_t explaination)
407 {
408 	emlxs_hba_t *hba = HBA;
409 	emlxs_port_dhc_t *port_dhc = &port->port_dhc;
410 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
411 	uint32_t pstate;
412 
413 	if ((state != NODE_STATE_NOCHANGE) && (node_dhc->state != state)) {
414 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_state_msg,
415 		    "Node:0x%x %s --> %s", ndlp->nlp_DID,
416 		    emlxs_dhc_nstate_xlate(node_dhc->state),
417 		    emlxs_dhc_nstate_xlate(state));
418 
419 		node_dhc->prev_state = node_dhc->state;
420 		node_dhc->state = (uint16_t)state;
421 
422 		/* Perform common functions based on state */
423 		switch (state) {
424 		case NODE_STATE_UNKNOWN:
425 		case NODE_STATE_AUTH_DISABLED:
426 			node_dhc->nlp_authrsp_tmo = 0;
427 			node_dhc->nlp_authrsp_tmocnt = 0;
428 			emlxs_dhc_set_reauth_time(port, ndlp, DISABLE);
429 			break;
430 
431 		case NODE_STATE_AUTH_SUCCESS:
432 			/* Record auth time */
433 			if (ndlp->nlp_DID == FABRIC_DID) {
434 				port_dhc->auth_time = DRV_TIME;
435 			} else if (node_dhc->parent_auth_cfg) {
436 				node_dhc->parent_auth_cfg->auth_time = DRV_TIME;
437 			}
438 			hba->rdn_flag = 0;
439 			node_dhc->nlp_authrsp_tmo = 0;
440 
441 			if (node_dhc->flag & NLP_SET_REAUTH_TIME) {
442 				emlxs_dhc_set_reauth_time(port, ndlp, ENABLE);
443 			}
444 			break;
445 
446 		default:
447 			break;
448 		}
449 
450 		/* Check for switch port */
451 		if (ndlp->nlp_DID == FABRIC_DID) {
452 			switch (state) {
453 			case NODE_STATE_UNKNOWN:
454 				pstate = ELX_FABRIC_STATE_UNKNOWN;
455 				break;
456 
457 			case NODE_STATE_AUTH_DISABLED:
458 				pstate = ELX_FABRIC_AUTH_DISABLED;
459 				break;
460 
461 			case NODE_STATE_AUTH_FAILED:
462 				pstate = ELX_FABRIC_AUTH_FAILED;
463 				break;
464 
465 			case NODE_STATE_AUTH_SUCCESS:
466 				pstate = ELX_FABRIC_AUTH_SUCCESS;
467 				break;
468 
469 				/* Auth active */
470 			default:
471 				if (port_dhc->state ==
472 				    ELX_FABRIC_AUTH_SUCCESS) {
473 					pstate = ELX_FABRIC_IN_REAUTH;
474 				} else if (port_dhc->state !=
475 				    ELX_FABRIC_IN_REAUTH) {
476 					pstate = ELX_FABRIC_IN_AUTH;
477 				}
478 				break;
479 			}
480 
481 			if (port_dhc->state != pstate) {
482 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_state_msg,
483 				    "Port: %s --> %s",
484 				    emlxs_dhc_pstate_xlate(port_dhc->state),
485 				    emlxs_dhc_pstate_xlate(pstate));
486 
487 				port_dhc->state = pstate;
488 			}
489 		}
490 	}
491 	/* Update auth status */
492 	mutex_enter(&hba->auth_lock);
493 	emlxs_dhc_status(port, ndlp, reason, explaination);
494 	mutex_exit(&hba->auth_lock);
495 
496 	return;
497 
498 } /* emlxs_dhc_state() */
499 
500 
501 /* auth_lock must be held when calling this */
502 extern void
emlxs_dhc_status(emlxs_port_t * port,emlxs_node_t * ndlp,uint32_t reason,uint32_t explaination)503 emlxs_dhc_status(emlxs_port_t *port, emlxs_node_t *ndlp, uint32_t reason,
504 	uint32_t explaination)
505 {
506 	emlxs_port_dhc_t *port_dhc;
507 	emlxs_node_dhc_t *node_dhc;
508 	dfc_auth_status_t *auth_status;
509 	uint32_t drv_time;
510 
511 	if (!ndlp || !ndlp->nlp_active || ndlp->node_dhc.state ==
512 	    NODE_STATE_UNKNOWN) {
513 		return;
514 	}
515 	port_dhc = &port->port_dhc;
516 	node_dhc = &ndlp->node_dhc;
517 
518 	/* Get auth status object */
519 	if (ndlp->nlp_DID == FABRIC_DID) {
520 		auth_status = &port_dhc->auth_status;
521 	} else if (node_dhc->parent_auth_cfg) {
522 		auth_status = &node_dhc->parent_auth_cfg->auth_status;
523 	} else {
524 		/* No auth status to be updated */
525 		return;
526 	}
527 
528 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_status_msg,
529 	    "Node:0x%x state=%s rsn=0x%x exp=0x%x (%x,%x)",
530 	    ndlp->nlp_DID, emlxs_dhc_nstate_xlate(node_dhc->state), reason,
531 	    explaination, auth_status->auth_state,
532 	    auth_status->auth_failReason);
533 
534 	/* Set state and auth_failReason */
535 	switch (node_dhc->state) {
536 	case NODE_STATE_UNKNOWN:	/* Connection */
537 		if (auth_status->auth_state != DFC_AUTH_STATE_FAILED) {
538 			auth_status->auth_state = DFC_AUTH_STATE_OFF;
539 			auth_status->auth_failReason = 0;
540 		}
541 		break;
542 
543 	case NODE_STATE_AUTH_DISABLED:
544 		auth_status->auth_state = DFC_AUTH_STATE_OFF;
545 		auth_status->auth_failReason = 0;
546 		break;
547 
548 	case NODE_STATE_AUTH_FAILED:
549 		/* Check failure reason and update if neccessary */
550 		switch (reason) {
551 		case AUTHRJT_FAILURE:	/* 0x01 */
552 		case AUTHRJT_LOGIC_ERR:	/* 0x02 */
553 			auth_status->auth_state = DFC_AUTH_STATE_FAILED;
554 			auth_status->auth_failReason = DFC_AUTH_FAIL_REJECTED;
555 			break;
556 
557 		case LSRJT_AUTH_REQUIRED:	/* 0x03 */
558 			switch (explaination) {
559 			case LSEXP_AUTH_REQUIRED:
560 				auth_status->auth_state = DFC_AUTH_STATE_FAILED;
561 				auth_status->auth_failReason =
562 				    DFC_AUTH_FAIL_LS_RJT;
563 				break;
564 			default:
565 				auth_status->auth_state = DFC_AUTH_STATE_FAILED;
566 				auth_status->auth_failReason =
567 				    DFC_AUTH_FAIL_REJECTED;
568 			}
569 			break;
570 
571 		case LSRJT_AUTH_LOGICAL_BSY:	/* 0x05 */
572 			auth_status->auth_state = DFC_AUTH_STATE_FAILED;
573 			auth_status->auth_failReason = DFC_AUTH_FAIL_BSY_LS_RJT;
574 			break;
575 
576 		case LSRJT_AUTH_ELS_NOT_SUPPORTED:	/* 0x0B */
577 			auth_status->auth_state = DFC_AUTH_STATE_FAILED;
578 			auth_status->auth_failReason = DFC_AUTH_FAIL_LS_RJT;
579 			break;
580 
581 		case LSRJT_AUTH_NOT_LOGGED_IN:	/* 0x09 */
582 			auth_status->auth_state = DFC_AUTH_STATE_FAILED;
583 			auth_status->auth_failReason = DFC_AUTH_FAIL_BSY_LS_RJT;
584 			break;
585 		}
586 
587 		/* Make sure the state is set to failed at this point */
588 		if (auth_status->auth_state != DFC_AUTH_STATE_FAILED) {
589 			auth_status->auth_state = DFC_AUTH_STATE_FAILED;
590 			auth_status->auth_failReason = DFC_AUTH_FAIL_GENERIC;
591 		}
592 		break;
593 
594 	case NODE_STATE_AUTH_SUCCESS:
595 		auth_status->auth_state = DFC_AUTH_STATE_ON;
596 		auth_status->auth_failReason = 0;
597 		break;
598 
599 		/* Authentication currently active */
600 	default:
601 		/* Set defaults */
602 		auth_status->auth_state = DFC_AUTH_STATE_INP;
603 		auth_status->auth_failReason = 0;
604 
605 		/* Check codes for exceptions */
606 		switch (reason) {
607 		case AUTHRJT_FAILURE:	/* 0x01 */
608 			switch (explaination) {
609 			case AUTHEXP_AUTH_FAILED:	/* 0x05 */
610 			case AUTHEXP_BAD_PAYLOAD:	/* 0x06 */
611 			case AUTHEXP_BAD_PROTOCOL:	/* 0x07 */
612 				auth_status->auth_state = DFC_AUTH_STATE_FAILED;
613 				auth_status->auth_failReason =
614 				    DFC_AUTH_FAIL_REJECTED;
615 				break;
616 			}
617 			break;
618 
619 		case AUTHRJT_LOGIC_ERR:	/* 0x02 */
620 			switch (explaination) {
621 			case AUTHEXP_MECH_UNUSABLE:	/* 0x01 */
622 			case AUTHEXP_DHGROUP_UNUSABLE:	/* 0x02 */
623 			case AUTHEXP_HASHFUNC_UNUSABLE:	/* 0x03 */
624 			case AUTHEXP_CONCAT_UNSUPP:	/* 0x09 */
625 			case AUTHEXP_BAD_PROTOVERS:	/* 0x0A */
626 				auth_status->auth_state = DFC_AUTH_STATE_FAILED;
627 				auth_status->auth_failReason =
628 				    DFC_AUTH_FAIL_REJECTED;
629 				break;
630 			}
631 			break;
632 
633 		case LSRJT_AUTH_REQUIRED:	/* 0x03 */
634 			switch (explaination) {
635 			case LSEXP_AUTH_REQUIRED:
636 				auth_status->auth_state = DFC_AUTH_STATE_FAILED;
637 				auth_status->auth_failReason =
638 				    DFC_AUTH_FAIL_LS_RJT;
639 				break;
640 			}
641 			break;
642 
643 		case LSRJT_AUTH_LOGICAL_BSY:	/* 0x05 */
644 			auth_status->auth_state = DFC_AUTH_STATE_FAILED;
645 			auth_status->auth_failReason = DFC_AUTH_FAIL_BSY_LS_RJT;
646 			break;
647 
648 		case LSRJT_AUTH_ELS_NOT_SUPPORTED:	/* 0x0B */
649 			auth_status->auth_state = DFC_AUTH_STATE_FAILED;
650 			auth_status->auth_failReason = DFC_AUTH_FAIL_LS_RJT;
651 			break;
652 
653 		case LSRJT_AUTH_NOT_LOGGED_IN:	/* 0x09 */
654 			auth_status->auth_state = DFC_AUTH_STATE_FAILED;
655 			auth_status->auth_failReason = DFC_AUTH_FAIL_BSY_LS_RJT;
656 			break;
657 		}
658 		break;
659 	}
660 
661 	if (auth_status->auth_state != DFC_AUTH_STATE_ON) {
662 		auth_status->time_until_next_auth = 0;
663 		auth_status->localAuth = 0;
664 		auth_status->remoteAuth = 0;
665 		auth_status->group_priority = 0;
666 		auth_status->hash_priority = 0;
667 		auth_status->type_priority = 0;
668 	} else {
669 		switch (node_dhc->nlp_reauth_status) {
670 		case NLP_HOST_REAUTH_ENABLED:
671 		case NLP_HOST_REAUTH_IN_PROGRESS:
672 			drv_time = DRV_TIME;
673 
674 			if (node_dhc->nlp_reauth_tmo > drv_time) {
675 				auth_status->time_until_next_auth =
676 				    node_dhc->nlp_reauth_tmo - drv_time;
677 			} else {
678 				auth_status->time_until_next_auth = 0;
679 			}
680 			break;
681 
682 		case NLP_HOST_REAUTH_DISABLED:
683 		default:
684 			auth_status->time_until_next_auth = 0;
685 			break;
686 		}
687 
688 		if (node_dhc->flag & NLP_REMOTE_AUTH) {
689 			auth_status->localAuth = 0;
690 			auth_status->remoteAuth = 1;
691 		} else {
692 			auth_status->localAuth = 1;
693 			auth_status->remoteAuth = 0;
694 		}
695 
696 		auth_status->type_priority = DFC_AUTH_TYPE_DHCHAP;
697 
698 		switch (node_dhc->nlp_auth_dhgpid) {
699 		case GROUP_NULL:
700 			auth_status->group_priority = ELX_GROUP_NULL;
701 			break;
702 
703 		case GROUP_1024:
704 			auth_status->group_priority = ELX_GROUP_1024;
705 			break;
706 
707 		case GROUP_1280:
708 			auth_status->group_priority = ELX_GROUP_1280;
709 			break;
710 
711 		case GROUP_1536:
712 			auth_status->group_priority = ELX_GROUP_1536;
713 			break;
714 
715 		case GROUP_2048:
716 			auth_status->group_priority = ELX_GROUP_2048;
717 			break;
718 		}
719 
720 		switch (node_dhc->nlp_auth_hashid) {
721 		case 0:
722 			auth_status->hash_priority = 0;
723 			break;
724 
725 		case AUTH_SHA1:
726 			auth_status->hash_priority = ELX_SHA1;
727 			break;
728 
729 		case AUTH_MD5:
730 			auth_status->hash_priority = ELX_MD5;
731 			break;
732 		}
733 	}
734 
735 	return;
736 
737 } /* emlxs_dhc_status()  */
738 
739 static char *
emlxs_dhc_pstate_xlate(uint32_t state)740 emlxs_dhc_pstate_xlate(uint32_t state)
741 {
742 	static char buffer[32];
743 	uint32_t i;
744 	uint32_t count;
745 
746 	count = sizeof (emlxs_pstate_table) / sizeof (emlxs_table_t);
747 	for (i = 0; i < count; i++) {
748 		if (state == emlxs_pstate_table[i].code) {
749 			return (emlxs_pstate_table[i].string);
750 		}
751 	}
752 
753 	(void) snprintf(buffer, sizeof (buffer), "state=0x%x", state);
754 	return (buffer);
755 
756 } /* emlxs_dhc_pstate_xlate() */
757 
758 
759 static char *
emlxs_dhc_nstate_xlate(uint32_t state)760 emlxs_dhc_nstate_xlate(uint32_t state)
761 {
762 	static char buffer[32];
763 	uint32_t i;
764 	uint32_t count;
765 
766 	count = sizeof (emlxs_nstate_table) / sizeof (emlxs_table_t);
767 	for (i = 0; i < count; i++) {
768 		if (state == emlxs_nstate_table[i].code) {
769 			return (emlxs_nstate_table[i].string);
770 		}
771 	}
772 
773 	(void) snprintf(buffer, sizeof (buffer), "state=0x%x", state);
774 	return (buffer);
775 
776 } /* emlxs_dhc_nstate_xlate() */
777 
778 
779 static uint32_t
emlxs_check_dhgp(emlxs_port_t * port,NODELIST * ndlp,uint32_t * dh_id,uint16_t cnt,uint32_t * dhgp_id)780 emlxs_check_dhgp(
781 	emlxs_port_t *port,
782 	NODELIST *ndlp,
783 	uint32_t *dh_id,
784 	uint16_t cnt,
785 	uint32_t *dhgp_id)
786 {
787 	uint32_t i, j, rc = 1;
788 	uint32_t wnt;
789 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
790 
791 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
792 	    "dhgp: 0x%x, id[0..4]=0x%x 0x%x 0x%x 0x%x 0x%x pri[1]=0x%x",
793 	    cnt, dh_id[0], dh_id[1], dh_id[2], dh_id[3], dh_id[4],
794 	    node_dhc->auth_cfg.dh_group_priority[1]);
795 
796 	/*
797 	 * Here are the rules, as the responder We always try to select ours
798 	 * highest setup
799 	 */
800 
801 	/* Check to see if there is any repeated dhgp in initiator's list */
802 	/* If available, it is a invalid payload */
803 	if (cnt >= 2) {
804 		for (i = 0; i <= cnt - 2; i++) {
805 			for (j = i + 1; j <= cnt - 1; j++) {
806 				if (dh_id[i] == dh_id[j]) {
807 					rc = 2;
808 					EMLXS_MSGF(EMLXS_CONTEXT,
809 					    &emlxs_fcsp_detail_msg,
810 					    ":Rpt dhid[%x]=%x dhid[%x]=%x",
811 					    i, dh_id[i], j, dh_id[j]);
812 					break;
813 				}
814 			}
815 
816 			if (rc == 2) {
817 				break;
818 			}
819 		}
820 
821 		if ((i == cnt - 1) && (j == cnt)) {
822 			rc = 1;
823 		}
824 		if (rc == 2) {
825 			/* duplicate invalid payload */
826 			return (rc);
827 		}
828 	}
829 	/* Check how many dhgps the responder specified */
830 	wnt = 0;
831 	while (node_dhc->auth_cfg.dh_group_priority[wnt] != 0xF) {
832 		wnt++;
833 	}
834 
835 	/* Determine the most suitable dhgp the responder should use */
836 	for (i = 0; i < wnt; i++) {
837 		for (j = 0; j < cnt; j++) {
838 			if (node_dhc->auth_cfg.dh_group_priority[i] ==
839 			    dh_id[j]) {
840 				rc = 0;
841 				*dhgp_id =
842 				    node_dhc->auth_cfg.dh_group_priority[i];
843 				break;
844 			}
845 		}
846 
847 		if (rc == 0) {
848 			break;
849 		}
850 	}
851 
852 	if (i == wnt) {
853 		/* no match */
854 		rc = 1;
855 		return (1);
856 	}
857 
858 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
859 	    "check_dhgp: dhgp_id=0x%x", *dhgp_id);
860 
861 	return (rc);
862 } /* emlxs_check_dhgp */
863 
864 
865 static void
emlxs_get_random_bytes(NODELIST * ndlp,uint8_t * rdn,uint32_t len)866 emlxs_get_random_bytes(
867 	NODELIST *ndlp,
868 	uint8_t *rdn,
869 	uint32_t len)
870 {
871 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
872 	hrtime_t now;
873 	uint8_t sha1_digest[20];
874 	SHA1_CTX sha1ctx;
875 
876 	now = gethrtime();
877 
878 	bzero(&sha1ctx, sizeof (SHA1_CTX));
879 	SHA1Init(&sha1ctx);
880 	SHA1Update(&sha1ctx, (void *) &node_dhc->auth_cfg.local_entity,
881 	    sizeof (NAME_TYPE));
882 	SHA1Update(&sha1ctx, (void *) &now, sizeof (hrtime_t));
883 	SHA1Final((void *) sha1_digest, &sha1ctx);
884 	bcopy((void *) &sha1_digest[0], (void *) &rdn[0], len);
885 
886 	return;
887 
888 } /* emlxs_get_random_bytes */
889 
890 
891 /* **************************** STATE MACHINE ************************** */
892 
893 static void *emlxs_dhchap_action[] =
894 {
895 	/* Action routine		Event */
896 
897 /* NODE_STATE_UNKNOWN  0x00 */
898 	(void *) emlxs_disc_neverdev,	/* DEVICE_RM */
899 	(void *) emlxs_disc_neverdev,	/* DEVICE_RECOVERY */
900 	(void *) emlxs_disc_neverdev,	/* RCV_AUTH_MSG */
901 	(void *) emlxs_disc_neverdev,	/* CMPL_AUTH_MSG */
902 
903 /* NODE_STATE_AUTH_DISABLED  0x01 */
904 	(void *) emlxs_disc_neverdev,	/* DEVICE_RM */
905 	(void *) emlxs_disc_neverdev,	/* DEVICE_RECOVERY */
906 	(void *) emlxs_disc_neverdev,	/* RCV_AUTH_MSG */
907 	(void *) emlxs_disc_neverdev,	/* CMPL_AUTH_MSG */
908 
909 /* NODE_STATE_AUTH_FAILED  0x02 */
910 	(void *) emlxs_device_rm_npr_node,	/* DEVICE_RM */
911 	(void *) emlxs_device_recov_npr_node,	/* DEVICE_RECOVERY */
912 	(void *) emlxs_rcv_auth_msg_npr_node,	/* RCV_AUTH_MSG */
913 	(void *) emlxs_cmpl_auth_msg_npr_node,	/* CMPL_AUTH_MSG */
914 
915 /* NODE_STATE_AUTH_SUCCESS  0x03 */
916 	(void *) emlxs_disc_neverdev,			/* DEVICE_RM */
917 	(void *) emlxs_device_recov_unmapped_node,	/* DEVICE_RECOVERY */
918 	(void *) emlxs_rcv_auth_msg_unmapped_node,	/* RCV_AUTH_MSG */
919 	(void *) emlxs_disc_neverdev,			/* CMPL_AUTH_MSG */
920 
921 /* NODE_STATE_AUTH_NEGOTIATE_ISSUE  0x04 */
922 	(void *) emlxs_device_rem_auth,	/* DEVICE_RM */
923 	(void *) emlxs_device_recov_auth, /* DEVICE_RECOVERY */
924 	(void *) emlxs_rcv_auth_msg_auth_negotiate_issue, /* RCV_AUTH_MSG  */
925 	(void *) emlxs_cmpl_auth_msg_auth_negotiate_issue, /* CMPL_AUTH_MSG */
926 
927 /* NODE_STATE_AUTH_NEGOTIATE_RCV  0x05 */
928 	(void *) emlxs_device_rem_auth,	/* DEVICE_RM */
929 	(void *) emlxs_device_recov_auth,	/* DEVICE_RECOVERY */
930 	(void *) emlxs_rcv_auth_msg_auth_negotiate_rcv,	/* RCV_AUTH_MSG */
931 	(void *) emlxs_cmpl_auth_msg_auth_negotiate_rcv, /* CMPL_AUTH_MSG */
932 
933 /* NODE_STATE_AUTH_NEGOTIATE_CMPL_WAIT4NEXT  0x06 */
934 	(void *) emlxs_device_rem_auth,	/* DEVICE_RM */
935 	(void *) emlxs_device_recov_auth,	/* DEVICE_RECOVERY */
936 	(void *) emlxs_rcv_auth_msg_auth_negotiate_cmpl_wait4next,
937 						/* RCV_AUTH_MSG */
938 	(void *) emlxs_cmpl_auth_msg_auth_negotiate_cmpl_wait4next,
939 						/* CMPL_AUTH_MSG */
940 
941 /* NODE_STATE_DHCHAP_CHALLENGE_ISSUE  0x07 */
942 	(void *) emlxs_device_rem_auth,	/* DEVICE_RM */
943 	(void *) emlxs_device_recov_auth,	/* DEVICE_RECOVERY */
944 	(void *) emlxs_rcv_auth_msg_dhchap_challenge_issue, /* RCV_AUTH_MSG */
945 	(void *) emlxs_cmpl_auth_msg_dhchap_challenge_issue, /* CMPL_AUTH_MSG */
946 
947 /* NODE_STATE_DHCHAP_REPLY_ISSUE  0x08 */
948 	(void *) emlxs_device_rem_auth,	/* DEVICE_RM */
949 	(void *) emlxs_device_recov_auth,	/* DEVICE_RECOVERY */
950 	(void *) emlxs_rcv_auth_msg_dhchap_reply_issue,	/* RCV_AUTH_MSG */
951 	(void *) emlxs_cmpl_auth_msg_dhchap_reply_issue, /* CMPL_AUTH_MSG */
952 
953 /* NODE_STATE_DHCHAP_CHALLENGE_CMPL_WAIT4NEXT  0x09 */
954 	(void *) emlxs_device_rem_auth,	/* DEVICE_RM */
955 	(void *) emlxs_device_recov_auth,	/* DEVICE_RECOVERY */
956 	(void *) emlxs_rcv_auth_msg_dhchap_challenge_cmpl_wait4next,
957 						/* RCV_AUTH_MSG   */
958 	(void *) emlxs_cmpl_auth_msg_dhchap_challenge_cmpl_wait4next,
959 						/* CMPL_AUTH_MSG */
960 
961 /* NODE_STATE_DHCHAP_REPLY_CMPL_WAIT4NEXT  0x0A */
962 	(void *) emlxs_device_rem_auth,	/* DEVICE_RM */
963 	(void *) emlxs_device_recov_auth,	/* DEVICE_RECOVERY */
964 	(void *) emlxs_rcv_auth_msg_dhchap_reply_cmpl_wait4next,
965 						/* RCV_AUTH_MSG */
966 	(void *) emlxs_cmpl_auth_msg_dhchap_reply_cmpl_wait4next,
967 						/* CMPL_AUTH_MSG */
968 
969 /* NODE_STATE_DHCHAP_SUCCESS_ISSUE  0x0B */
970 	(void *) emlxs_device_rem_auth,	/* DEVICE_RM */
971 	(void *) emlxs_device_recov_auth,	/* DEVICE_RECOVERY */
972 	(void *) emlxs_rcv_auth_msg_dhchap_success_issue,
973 						/* RCV_AUTH_MSG */
974 	(void *) emlxs_cmpl_auth_msg_dhchap_success_issue,
975 						/* CMPL_AUTH_MSG */
976 
977 /* NODE_STATE_DHCHAP_SUCCESS_ISSUE_WAIT4NEXT  0x0C */
978 	(void *) emlxs_device_rem_auth,	/* DEVICE_RM */
979 	(void *) emlxs_device_recov_auth,	/* DEVICE_RECOVERY */
980 	(void *) emlxs_rcv_auth_msg_dhchap_success_issue_wait4next,
981 						/* RCV_AUTH_MSG */
982 	(void *) emlxs_cmpl_auth_msg_dhchap_success_issue_wait4next,
983 						/* CMPL_AUTH_MSG */
984 
985 /* NODE_STATE_DHCHAP_SUCCESS_CMPL_WAIT4NEXT  0x0D */
986 	(void *) emlxs_device_rem_auth,	/* DEVICE_RM */
987 	(void *) emlxs_device_recov_auth,	/* DEVICE_RECOVERY */
988 	(void *) emlxs_rcv_auth_msg_dhchap_success_cmpl_wait4next,
989 						/* RCV_AUTH_MSG */
990 	(void *) emlxs_cmpl_auth_msg_dhchap_success_cmpl_wait4next,
991 						/* CMPL_AUTH_MSG */
992 
993 }; /* emlxs_dhchap_action[] */
994 
995 
996 extern int
emlxs_dhchap_state_machine(emlxs_port_t * port,CHANNEL * cp,IOCBQ * iocbq,MATCHMAP * mp,NODELIST * ndlp,int evt)997 emlxs_dhchap_state_machine(emlxs_port_t *port, CHANNEL *cp,
998 		IOCBQ *iocbq, MATCHMAP *mp,
999 		NODELIST *ndlp, int evt)
1000 {
1001 	emlxs_hba_t *hba = HBA;
1002 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
1003 	uint32_t rc;
1004 	uint32_t(*func) (emlxs_port_t *, CHANNEL *, IOCBQ *, MATCHMAP *,
1005 	    NODELIST *, uint32_t);
1006 
1007 	mutex_enter(&hba->dhc_lock);
1008 
1009 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_event_msg,
1010 	    "%s: did=0x%x",
1011 	    emlxs_dhc_event_xlate(evt), ndlp->nlp_DID);
1012 
1013 	node_dhc->disc_refcnt++;
1014 
1015 	func = (uint32_t(*) (emlxs_port_t *, CHANNEL *, IOCBQ *, MATCHMAP *,
1016 	    NODELIST *, uint32_t))
1017 	    emlxs_dhchap_action[(node_dhc->state * NODE_EVENT_MAX_EVENT) + evt];
1018 
1019 	rc = (func) (port, cp, iocbq, mp, ndlp, evt);
1020 
1021 	node_dhc->disc_refcnt--;
1022 
1023 	mutex_exit(&hba->dhc_lock);
1024 
1025 	return (rc);
1026 
1027 } /* emlxs_dhchap_state_machine() */
1028 
1029 /* ARGSUSED */
1030 static uint32_t
emlxs_disc_neverdev(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)1031 emlxs_disc_neverdev(
1032 emlxs_port_t *port,
1033 /* CHANNEL * rp, */ void *arg1,
1034 /* IOCBQ * iocbq, */ void *arg2,
1035 /* MATCHMAP * mp, */ void *arg3,
1036 /* NODELIST * ndlp */ void *arg4,
1037 uint32_t evt)
1038 {
1039 	NODELIST *ndlp = (NODELIST *) arg4;
1040 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
1041 
1042 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
1043 	    "disc_neverdev: did=0x%x.",
1044 	    ndlp->nlp_DID);
1045 
1046 	emlxs_dhc_state(port, ndlp, NODE_STATE_UNKNOWN, 0, 0);
1047 
1048 	return (node_dhc->state);
1049 
1050 } /* emlxs_disc_neverdev() */
1051 
1052 
1053 /*
1054  * ! emlxs_cmpl_dhchap_challenge_issue
1055  *
1056  * \pre \post \param   cmdiocb \param   rspiocb \return  void
1057  *
1058  * \b Description: iocb_cmpl callback function. when the ELS DHCHAP_Challenge
1059  * msg sent back got the ACC/RJT from initiator.
1060  *
1061  */
1062 static void
emlxs_cmpl_dhchap_challenge_issue(fc_packet_t * pkt)1063 emlxs_cmpl_dhchap_challenge_issue(fc_packet_t *pkt)
1064 {
1065 	emlxs_port_t *port = pkt->pkt_ulp_private;
1066 	emlxs_buf_t *sbp;
1067 	NODELIST *ndlp;
1068 	uint32_t did;
1069 
1070 	did = pkt->pkt_cmd_fhdr.d_id;
1071 	sbp = (emlxs_buf_t *)pkt->pkt_fca_private;
1072 	ndlp = sbp->node;
1073 
1074 	if (!ndlp) {
1075 		ndlp = emlxs_node_find_did(port, did, 1);
1076 	}
1077 	if (pkt->pkt_state != FC_PKT_SUCCESS) {
1078 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
1079 		    "cmpl_dhchap_challenge_issue: did=0x%x state=%x",
1080 		    did, pkt->pkt_state);
1081 	} else {
1082 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
1083 		    "cmpl_dhchap_challenge_issue: did=0x%x. Succcess.",
1084 		    did);
1085 	}
1086 
1087 	if (ndlp) {
1088 		if (pkt->pkt_state == FC_PKT_SUCCESS) {
1089 			(void) emlxs_dhchap_state_machine(port, NULL, NULL,
1090 			    NULL, ndlp, NODE_EVENT_CMPL_AUTH_MSG);
1091 		}
1092 	}
1093 	emlxs_pkt_free(pkt);
1094 
1095 	return;
1096 
1097 } /* emlxs_cmpl_dhchap_challenge_issue */
1098 
1099 
1100 
1101 
1102 /*
1103  * ! emlxs_cmpl_dhchap_success_issue
1104  *
1105  * \pre \post \param   phba \param   cmdiocb \param   rspiocb \return  void
1106  *
1107  * \b Description: iocb_cmpl callback function.
1108  *
1109  */
1110 static void
emlxs_cmpl_dhchap_success_issue(fc_packet_t * pkt)1111 emlxs_cmpl_dhchap_success_issue(fc_packet_t *pkt)
1112 {
1113 	emlxs_port_t *port = pkt->pkt_ulp_private;
1114 	NODELIST *ndlp;
1115 	uint32_t did;
1116 	emlxs_buf_t *sbp;
1117 
1118 	did = pkt->pkt_cmd_fhdr.d_id;
1119 	sbp = (emlxs_buf_t *)pkt->pkt_fca_private;
1120 	ndlp = sbp->node;
1121 
1122 	if (!ndlp) {
1123 		ndlp = emlxs_node_find_did(port, did, 1);
1124 	}
1125 	if (pkt->pkt_state != FC_PKT_SUCCESS) {
1126 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
1127 		    "cmpl_dhchap_success_issue: 0x%x %x. No retry.",
1128 		    did, pkt->pkt_state);
1129 	} else {
1130 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
1131 		    "cmpl_dhchap_success_issue: did=0x%x. Succcess.",
1132 		    did);
1133 	}
1134 
1135 	if (ndlp) {
1136 		if (pkt->pkt_state == FC_PKT_SUCCESS) {
1137 			(void) emlxs_dhchap_state_machine(port, NULL, NULL,
1138 			    NULL, ndlp, NODE_EVENT_CMPL_AUTH_MSG);
1139 		}
1140 	}
1141 	emlxs_pkt_free(pkt);
1142 
1143 	return;
1144 
1145 } /* emlxs_cmpl_dhchap_success_issue */
1146 
1147 
1148 /*
1149  * if rsp == NULL, this is only the DHCHAP_Success msg
1150  *
1151  * if rsp != NULL, DHCHAP_Success contains rsp to the challenge.
1152  */
1153 /* ARGSUSED */
1154 uint32_t
emlxs_issue_dhchap_success(emlxs_port_t * port,NODELIST * ndlp,int retry,uint8_t * rsp)1155 emlxs_issue_dhchap_success(
1156 	emlxs_port_t *port,
1157 	NODELIST *ndlp,
1158 	int retry,
1159 	uint8_t *rsp)
1160 {
1161 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
1162 	fc_packet_t *pkt;
1163 	uint32_t cmd_size;
1164 	uint32_t rsp_size;
1165 	uint8_t *pCmd;
1166 	uint16_t cmdsize;
1167 	DHCHAP_SUCCESS_HDR *ap;
1168 	uint8_t *tmp;
1169 	uint32_t len;
1170 	uint32_t ret;
1171 
1172 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
1173 	    "issue_dhchap_success: did=0x%x", ndlp->nlp_DID);
1174 
1175 	if (ndlp->nlp_DID == FABRIC_DID) {
1176 		if (node_dhc->nlp_auth_hashid == AUTH_MD5)
1177 			len = MD5_LEN;
1178 		else
1179 			len = SHA1_LEN;
1180 	} else {
1181 		len = (node_dhc->nlp_auth_hashid == AUTH_MD5) ?
1182 		    MD5_LEN : SHA1_LEN;
1183 	}
1184 
1185 	if (rsp == NULL) {
1186 		cmdsize = sizeof (DHCHAP_SUCCESS_HDR);
1187 	} else {
1188 
1189 		cmdsize = sizeof (DHCHAP_SUCCESS_HDR) + len;
1190 	}
1191 
1192 	cmd_size = cmdsize;
1193 	rsp_size = 4;
1194 
1195 	if ((pkt = emlxs_prep_els_fc_pkt(port, ndlp->nlp_DID, cmd_size,
1196 	    rsp_size, 0, KM_NOSLEEP)) == NULL) {
1197 		return (1);
1198 	}
1199 	pCmd = (uint8_t *)pkt->pkt_cmd;
1200 
1201 	ap = (DHCHAP_SUCCESS_HDR *)pCmd;
1202 	tmp = (uint8_t *)pCmd;
1203 
1204 	ap->auth_els_code = ELS_CMD_AUTH_CODE;
1205 	ap->auth_els_flags = 0x0;
1206 	ap->auth_msg_code = DHCHAP_SUCCESS;
1207 	ap->proto_version = 0x01;
1208 
1209 	/*
1210 	 * In case of rsp == NULL meaning that this is DHCHAP_Success issued
1211 	 * when Host is the initiator AND this DHCHAP_Success is issused in
1212 	 * response to the bi-directional authentication, meaning Host
1213 	 * authenticate another entity, therefore no more DHCHAP_Success
1214 	 * expected. OR this DHCHAP_Success is issued by host when host is
1215 	 * the responder BUT it is uni-directional auth, therefore no more
1216 	 * DHCHAP_Success expected.
1217 	 *
1218 	 * In case of rsp != NULL it indicates this DHCHAP_Success is issued
1219 	 * when host is the responder AND this DHCHAP_Success has reply
1220 	 * embedded therefore the host expects DHCHAP_Success from other
1221 	 * entity in transaction.
1222 	 */
1223 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
1224 	    "issue_dhchap_success: 0x%x 0x%x 0x%x 0x%x 0x%x %p",
1225 	    ndlp->nlp_DID, node_dhc->nlp_auth_hashid,
1226 	    node_dhc->nlp_auth_tranid_rsp,
1227 	    node_dhc->nlp_auth_tranid_ini, cmdsize, rsp);
1228 
1229 	if (rsp == NULL) {
1230 		ap->msg_len = LE_SWAP32(0x00000004);
1231 		ap->RspVal_len = 0x0;
1232 
1233 		node_dhc->fc_dhchap_success_expected = 0;
1234 	} else {
1235 		node_dhc->fc_dhchap_success_expected = 1;
1236 
1237 		ap->msg_len = LE_SWAP32(4 + len);
1238 
1239 		tmp += sizeof (DHCHAP_SUCCESS_HDR) - sizeof (uint32_t);
1240 		*(uint32_t *)tmp = LE_SWAP32(len);
1241 		tmp += sizeof (uint32_t);
1242 		bcopy((void *)rsp, (void *)tmp, len);
1243 	}
1244 
1245 	if (node_dhc->nlp_reauth_status == NLP_HOST_REAUTH_IN_PROGRESS) {
1246 		ap->tran_id = LE_SWAP32(node_dhc->nlp_auth_tranid_rsp);
1247 	} else {
1248 		if (node_dhc->nlp_auth_flag == 2) {
1249 			ap->tran_id =
1250 			    LE_SWAP32(node_dhc->nlp_auth_tranid_rsp);
1251 		} else if (node_dhc->nlp_auth_flag == 1) {
1252 			ap->tran_id =
1253 			    LE_SWAP32(node_dhc->nlp_auth_tranid_ini);
1254 		} else {
1255 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_debug_msg,
1256 			    "is_dhch_success: (1) 0x%x 0x%x 0x%x 0x%x",
1257 			    ndlp->nlp_DID, node_dhc->nlp_auth_flag,
1258 			    node_dhc->nlp_auth_tranid_rsp,
1259 			    node_dhc->nlp_auth_tranid_ini);
1260 
1261 			return (1);
1262 		}
1263 	}
1264 
1265 	pkt->pkt_comp = emlxs_cmpl_dhchap_success_issue;
1266 
1267 	ret = emlxs_pkt_send(pkt, 1);
1268 
1269 	if (ret != FC_SUCCESS) {
1270 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
1271 		    "issue_dhchap_success: Unable to send packet. 0x%x",
1272 		    ret);
1273 
1274 		emlxs_pkt_free(pkt);
1275 
1276 		return (1);
1277 	}
1278 	return (0);
1279 
1280 } /* emlxs_issue_dhchap_success */
1281 
1282 
1283 /*
1284  * ! emlxs_cmpl_auth_reject_issue
1285  *
1286  * \pre \post \param   phba \param   cmdiocb \param   rspiocb \return  void
1287  *
1288  * \b Description: iocb_cmpl callback function.
1289  *
1290  */
1291 static void
emlxs_cmpl_auth_reject_issue(fc_packet_t * pkt)1292 emlxs_cmpl_auth_reject_issue(fc_packet_t *pkt)
1293 {
1294 	emlxs_port_t *port = pkt->pkt_ulp_private;
1295 	emlxs_buf_t *sbp;
1296 	NODELIST *ndlp;
1297 	uint32_t did;
1298 
1299 	did = pkt->pkt_cmd_fhdr.d_id;
1300 	sbp = (emlxs_buf_t *)pkt->pkt_fca_private;
1301 	ndlp = sbp->node;
1302 
1303 	if (!ndlp) {
1304 		ndlp = emlxs_node_find_did(port, did, 1);
1305 	}
1306 	if (pkt->pkt_state != FC_PKT_SUCCESS) {
1307 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
1308 		    "cmpl_auth_reject_issue: 0x%x %x. No retry.",
1309 		    did, pkt->pkt_state);
1310 	} else {
1311 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
1312 		    "cmpl_auth_reject_issue: did=0x%x. Succcess.",
1313 		    did);
1314 	}
1315 
1316 	if (ndlp) {
1317 		/* setup the new state */
1318 		emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_FAILED, 0, 0);
1319 
1320 		if (pkt->pkt_state == FC_PKT_SUCCESS) {
1321 			(void) emlxs_dhchap_state_machine(port, NULL, NULL,
1322 			    NULL, ndlp, NODE_EVENT_CMPL_AUTH_MSG);
1323 		}
1324 	}
1325 	emlxs_pkt_free(pkt);
1326 
1327 	return;
1328 
1329 } /* emlxs_cmpl_auth_reject_issue */
1330 
1331 
1332 /*
1333  * If Logical Error and Reason Code Explanation is "Restart Authentication
1334  * Protocol" then the Transaction Identifier could be
1335  * any value.
1336  */
1337 /* ARGSUSED */
1338 static uint32_t
emlxs_issue_auth_reject(emlxs_port_t * port,NODELIST * ndlp,int retry,uint32_t * arg,uint8_t ReasonCode,uint8_t ReasonCodeExplanation)1339 emlxs_issue_auth_reject(
1340 	emlxs_port_t *port,
1341 	NODELIST *ndlp,
1342 	int retry,
1343 	uint32_t *arg,
1344 	uint8_t ReasonCode,
1345 	uint8_t ReasonCodeExplanation)
1346 {
1347 	fc_packet_t *pkt;
1348 	uint32_t cmd_size;
1349 	uint32_t rsp_size;
1350 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
1351 	uint16_t cmdsize;
1352 	AUTH_RJT *ap;
1353 	char info[64];
1354 
1355 	if (node_dhc->nlp_authrsp_tmo) {
1356 		node_dhc->nlp_authrsp_tmo = 0;
1357 	}
1358 	cmdsize = sizeof (AUTH_RJT);
1359 	cmd_size = cmdsize;
1360 	rsp_size = 4;
1361 
1362 	if ((pkt = emlxs_prep_els_fc_pkt(port, ndlp->nlp_DID, cmd_size,
1363 	    rsp_size, 0, KM_NOSLEEP)) == NULL) {
1364 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
1365 		    "Auth reject failed: Unable to allocate pkt. 0x%x %x %x",
1366 		    ndlp->nlp_DID, ReasonCode, ReasonCodeExplanation);
1367 
1368 		return (1);
1369 	}
1370 	ap = (AUTH_RJT *) pkt->pkt_cmd;
1371 	ap->auth_els_code = ELS_CMD_AUTH_CODE;
1372 	ap->auth_els_flags = 0x0;
1373 	ap->auth_msg_code = AUTH_REJECT;
1374 	ap->proto_version = 0x01;
1375 	ap->msg_len = LE_SWAP32(4);
1376 
1377 	if (node_dhc->nlp_auth_flag == 2) {
1378 		ap->tran_id = LE_SWAP32(node_dhc->nlp_auth_tranid_rsp);
1379 	} else if (node_dhc->nlp_auth_flag == 1) {
1380 		ap->tran_id = LE_SWAP32(node_dhc->nlp_auth_tranid_ini);
1381 	} else {
1382 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
1383 		    "Auth reject failed.Invalid flag=%d. 0x%x %x expl=%x",
1384 		    ndlp->nlp_DID, node_dhc->nlp_auth_flag, ReasonCode,
1385 		    ReasonCodeExplanation);
1386 
1387 		emlxs_pkt_free(pkt);
1388 
1389 		return (1);
1390 	}
1391 
1392 	ap->ReasonCode = ReasonCode;
1393 	ap->ReasonCodeExplanation = ReasonCodeExplanation;
1394 
1395 	pkt->pkt_comp = emlxs_cmpl_auth_reject_issue;
1396 
1397 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_debug_msg,
1398 	    "Auth reject: did=0x%x reason=%x expl=%x",
1399 	    ndlp->nlp_DID, ReasonCode, ReasonCodeExplanation);
1400 
1401 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
1402 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
1403 		    "Auth reject failed. Unable to send pkt. 0x%x %x expl=%x",
1404 		    ndlp->nlp_DID, node_dhc->nlp_auth_flag, ReasonCode,
1405 		    ReasonCodeExplanation);
1406 
1407 		emlxs_pkt_free(pkt);
1408 
1409 		return (1);
1410 	}
1411 	(void) snprintf(info, sizeof (info),
1412 	    "Auth-Reject: ReasonCode=0x%x, ReasonCodeExplanation=0x%x",
1413 	    ReasonCode, ReasonCodeExplanation);
1414 
1415 	emlxs_log_auth_event(port, ndlp, "issue_auth_reject", info);
1416 
1417 	return (0);
1418 
1419 } /* emlxs_issue_auth_reject */
1420 
1421 
1422 static fc_packet_t *
emlxs_prep_els_fc_pkt(emlxs_port_t * port,uint32_t d_id,uint32_t cmd_size,uint32_t rsp_size,uint32_t datalen,int32_t sleepflag)1423 	emlxs_prep_els_fc_pkt(
1424 	emlxs_port_t *port,
1425 	uint32_t d_id,
1426 	uint32_t cmd_size,
1427 	uint32_t rsp_size,
1428 	uint32_t datalen,
1429 	int32_t sleepflag)
1430 {
1431 	fc_packet_t *pkt;
1432 
1433 	/* simulate the ULP stack's fc_packet send out */
1434 	if (!(pkt = emlxs_pkt_alloc(port, cmd_size, rsp_size,
1435 	    datalen, sleepflag))) {
1436 		return (NULL);
1437 	}
1438 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
1439 	pkt->pkt_timeout = 35;
1440 
1441 	/* Build the fc header */
1442 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(d_id);
1443 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_REQ;
1444 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
1445 	pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
1446 	pkt->pkt_cmd_fhdr.f_ctl =
1447 	    F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
1448 	pkt->pkt_cmd_fhdr.seq_id = 0;
1449 	pkt->pkt_cmd_fhdr.df_ctl = 0;
1450 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
1451 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
1452 	pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
1453 	pkt->pkt_cmd_fhdr.ro = 0;
1454 
1455 	return ((fc_packet_t *)pkt);
1456 
1457 } /* emlxs_prep_els_fc_pkt */
1458 
1459 
1460 /*
1461  * ! emlxs_issue_auth_negotiate
1462  *
1463  * \pre \post \param   port \param   ndlp \param   retry \param   flag \return
1464  * int
1465  *
1466  * \b Description:
1467  *
1468  * The routine is invoked when host as the authentication initiator which
1469  * issue the AUTH_ELS command AUTH_Negotiate to the other
1470  * entity ndlp. When this Auth_Negotiate command is completed, the iocb_cmpl
1471  * will get called as the solicited mbox cmd
1472  * callback. Some switch only support NULL dhchap in which case negotiate
1473  * should be modified to only have NULL DH specificed.
1474  *
1475  */
1476 /* ARGSUSED */
1477 static int
emlxs_issue_auth_negotiate(emlxs_port_t * port,emlxs_node_t * ndlp,uint8_t retry)1478 emlxs_issue_auth_negotiate(
1479 	emlxs_port_t *port,
1480 	emlxs_node_t *ndlp,
1481 	uint8_t retry)
1482 {
1483 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
1484 	fc_packet_t *pkt;
1485 	uint32_t cmd_size;
1486 	uint32_t rsp_size;
1487 	uint16_t cmdsize;
1488 	AUTH_MSG_NEGOT_NULL_1 *null_ap1;
1489 	AUTH_MSG_NEGOT_NULL_2 *null_ap2;
1490 	uint32_t num_hs = 0;
1491 	uint8_t flag;
1492 	AUTH_MSG_NEGOT_1 *ap1;
1493 	AUTH_MSG_NEGOT_2 *ap2;
1494 	uint16_t para_len = 0;
1495 	uint16_t hash_wcnt = 0;
1496 	uint16_t dhgp_wcnt = 0;
1497 
1498 
1499 	emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_NEGOTIATE_ISSUE, 0, 0);
1500 
1501 	/* Full DH group support limit:2, only NULL group support limit:1 */
1502 	flag = (node_dhc->nlp_auth_limit == 2) ? 1 : 0;
1503 
1504 	/* first: determine the cmdsize based on the auth cfg parameters */
1505 	if (flag == 1) {
1506 		/* May be Full DH group + 2 hash may not be */
1507 		cmdsize = sizeof (AUTH_MSG_NEGOT_NULL);
1508 
1509 		cmdsize += 2 + 2;	/* name tag: 2, name length: 2 */
1510 		cmdsize += 8;	/* WWN: 8 */
1511 		cmdsize += 4;	/* num of protocol: 4 */
1512 		cmdsize += 4;	/* protocol parms length: 4 */
1513 		cmdsize += 4;	/* protocol id: 4 */
1514 		para_len += 4;
1515 
1516 		cmdsize += 2 + 2;	/* hashlist: tag: 2, count:2 */
1517 		para_len += 4;
1518 
1519 		if (node_dhc->auth_cfg.hash_priority[1] == 0x00) {
1520 			/* only one hash func */
1521 			cmdsize += 4;
1522 			num_hs = 1;
1523 			para_len += 4;
1524 			hash_wcnt = 1;
1525 		} else {
1526 			/* two hash funcs */
1527 			cmdsize += 4 + 4;
1528 			num_hs = 2;
1529 			para_len += 4 + 4;
1530 			hash_wcnt = 2;
1531 		}
1532 
1533 		cmdsize += 2 + 2;
1534 		para_len += 4;
1535 		if (node_dhc->auth_cfg.dh_group_priority[1] == 0xf) {
1536 			/* only one dhgp specified: could be NULL or non-NULL */
1537 			cmdsize += 4;
1538 			para_len += 4;
1539 			dhgp_wcnt = 1;
1540 
1541 		} else if (node_dhc->auth_cfg.dh_group_priority[2] == 0xf) {
1542 			/* two dhgps specified */
1543 			cmdsize += 4 + 4;
1544 			para_len += 4 + 4;
1545 			dhgp_wcnt = 2;
1546 
1547 		} else if (node_dhc->auth_cfg.dh_group_priority[3] == 0xf) {
1548 			/* three dhgps specified */
1549 			cmdsize += 4 + 4 + 4;
1550 			para_len += 4 + 4 + 4;
1551 			dhgp_wcnt = 3;
1552 
1553 		} else if (node_dhc->auth_cfg.dh_group_priority[4] == 0xf) {
1554 			/* four dhgps specified */
1555 			cmdsize += 4 + 4 + 4 + 4;
1556 			para_len += 4 + 4 + 4 + 4;
1557 			dhgp_wcnt = 4;
1558 
1559 		} else if (node_dhc->auth_cfg.dh_group_priority[5] == 0xf) {
1560 			cmdsize += 4 + 4 + 4 + 4 + 4;
1561 			para_len += 4 + 4 + 4 + 4 + 4;
1562 			dhgp_wcnt = 5;
1563 
1564 		}
1565 	} else {
1566 		cmdsize = sizeof (AUTH_MSG_NEGOT_NULL);
1567 
1568 		/*
1569 		 * get the right payload size in byte: determined by config
1570 		 * parameters
1571 		 */
1572 		cmdsize += 2 + 2 + 8;	/* name tag:2, name length:2, name */
1573 					/* value content:8 */
1574 		cmdsize += 4;	/* number of usable authentication */
1575 				/* protocols:4 */
1576 		cmdsize += 4;	/* auth protocol params length: 4 */
1577 		cmdsize += 4;	/* auth protocol identifier: 4 */
1578 
1579 		/* hash list infor */
1580 		cmdsize += 4;	/* hashlist: tag:2, count:2 */
1581 
1582 		if (node_dhc->auth_cfg.hash_priority[1] == 0x00) {
1583 			cmdsize += 4;	/* only one hash function provided */
1584 			num_hs = 1;
1585 		} else {
1586 			num_hs = 2;
1587 			cmdsize += 4 + 4;	/* sha1: 4, md5: 4 */
1588 		}
1589 
1590 		/* dhgp list info */
1591 		/* since this is NULL DH group */
1592 		cmdsize += 4;	/* dhgroup: tag:2, count:2 */
1593 		cmdsize += 4;	/* set it to zero */
1594 	}
1595 
1596 	cmd_size = cmdsize;
1597 	rsp_size = 4;
1598 
1599 	if ((pkt = emlxs_prep_els_fc_pkt(port, ndlp->nlp_DID, cmd_size,
1600 	    rsp_size, 0, KM_NOSLEEP)) == NULL) {
1601 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
1602 		    "issue_auth_negotiate: Unable to allocate pkt. 0x%x %d",
1603 		    ndlp->nlp_DID, cmd_size);
1604 
1605 		return (1);
1606 	}
1607 	/* Fill in AUTH_MSG_NEGOT payload */
1608 	if (flag == 1) {
1609 		if (hash_wcnt == 1) {
1610 			ap1 = (AUTH_MSG_NEGOT_1 *)pkt->pkt_cmd;
1611 			ap1->auth_els_code = ELS_CMD_AUTH_CODE;
1612 			ap1->auth_els_flags = 0x00;
1613 			ap1->auth_msg_code = AUTH_NEGOTIATE;
1614 			ap1->proto_version = 0x01;
1615 			ap1->msg_len = LE_SWAP32(cmdsize -
1616 			    sizeof (AUTH_MSG_NEGOT_NULL));
1617 		} else {
1618 			ap2 = (AUTH_MSG_NEGOT_2 *)pkt->pkt_cmd;
1619 			ap2->auth_els_code = ELS_CMD_AUTH_CODE;
1620 			ap2->auth_els_flags = 0x00;
1621 			ap2->auth_msg_code = AUTH_NEGOTIATE;
1622 			ap2->proto_version = 0x01;
1623 			ap2->msg_len = LE_SWAP32(cmdsize -
1624 			    sizeof (AUTH_MSG_NEGOT_NULL));
1625 		}
1626 	} else {
1627 		if (node_dhc->auth_cfg.hash_priority[1] == 0x00) {
1628 			null_ap1 = (AUTH_MSG_NEGOT_NULL_1 *)pkt->pkt_cmd;
1629 			null_ap1->auth_els_code = ELS_CMD_AUTH_CODE;
1630 			null_ap1->auth_els_flags = 0x0;
1631 			null_ap1->auth_msg_code = AUTH_NEGOTIATE;
1632 			null_ap1->proto_version = 0x01;
1633 			null_ap1->msg_len = LE_SWAP32(cmdsize -
1634 			    sizeof (AUTH_MSG_NEGOT_NULL));
1635 
1636 		} else {
1637 			null_ap2 = (AUTH_MSG_NEGOT_NULL_2 *)pkt->pkt_cmd;
1638 			null_ap2->auth_els_code = ELS_CMD_AUTH_CODE;
1639 			null_ap2->auth_els_flags = 0x0;
1640 			null_ap2->auth_msg_code = AUTH_NEGOTIATE;
1641 			null_ap2->proto_version = 0x01;
1642 			null_ap2->msg_len = LE_SWAP32(cmdsize -
1643 			    sizeof (AUTH_MSG_NEGOT_NULL));
1644 		}
1645 	}
1646 
1647 	/*
1648 	 * For host reauthentication heart beat, the tran_id is incremented
1649 	 * by one for each heart beat being fired and round back to 1 when
1650 	 * 0xffffffff is reached. tran_id 0 is reserved as the initial linkup
1651 	 * authentication transaction id.
1652 	 */
1653 
1654 	/* responder flag:2, initiator flag:1 */
1655 	node_dhc->nlp_auth_flag = 2;	/* ndlp is the always the auth */
1656 					/* responder */
1657 
1658 	if (node_dhc->nlp_reauth_status == NLP_HOST_REAUTH_IN_PROGRESS) {
1659 		if (node_dhc->nlp_auth_tranid_rsp == 0xffffffff) {
1660 			node_dhc->nlp_auth_tranid_rsp = 1;
1661 		} else {
1662 			node_dhc->nlp_auth_tranid_rsp++;
1663 		}
1664 	} else {	/* !NLP_HOST_REAUTH_IN_PROGRESS */
1665 		node_dhc->nlp_auth_tranid_rsp = 0;
1666 	}
1667 
1668 	if (flag == 1) {
1669 		if (hash_wcnt == 1) {
1670 			ap1->tran_id =
1671 			    LE_SWAP32(node_dhc->nlp_auth_tranid_rsp);
1672 
1673 			ap1->params.name_tag = AUTH_NAME_ID;
1674 			ap1->params.name_len = AUTH_NAME_LEN;
1675 			bcopy((void *)&port->wwpn,
1676 			    (void *) &ap1->params.nodeName, sizeof (NAME_TYPE));
1677 			ap1->params.proto_num = AUTH_PROTO_NUM;
1678 			ap1->params.para_len = LE_SWAP32(para_len);
1679 			ap1->params.proto_id = AUTH_DHCHAP;
1680 			ap1->params.HashList_tag = HASH_LIST_TAG;
1681 			ap1->params.HashList_wcnt = LE_SWAP16(hash_wcnt);
1682 			ap1->params.HashList_value1 =
1683 			    node_dhc->auth_cfg.hash_priority[0];
1684 			ap1->params.DHgIDList_tag = DHGID_LIST_TAG;
1685 			ap1->params.DHgIDList_wnt = LE_SWAP16(dhgp_wcnt);
1686 
1687 			switch (dhgp_wcnt) {
1688 			case 5:
1689 				ap1->params.DHgIDList_g4 =
1690 				    (node_dhc->auth_cfg.dh_group_priority[4]);
1691 				ap1->params.DHgIDList_g3 =
1692 				    (node_dhc->auth_cfg.dh_group_priority[3]);
1693 				ap1->params.DHgIDList_g2 =
1694 				    (node_dhc->auth_cfg.dh_group_priority[2]);
1695 				ap1->params.DHgIDList_g1 =
1696 				    (node_dhc->auth_cfg.dh_group_priority[1]);
1697 				ap1->params.DHgIDList_g0 =
1698 				    (node_dhc->auth_cfg.dh_group_priority[0]);
1699 				break;
1700 			case 4:
1701 				ap1->params.DHgIDList_g3 =
1702 				    (node_dhc->auth_cfg.dh_group_priority[3]);
1703 				ap1->params.DHgIDList_g2 =
1704 				    (node_dhc->auth_cfg.dh_group_priority[2]);
1705 				ap1->params.DHgIDList_g1 =
1706 				    (node_dhc->auth_cfg.dh_group_priority[1]);
1707 				ap1->params.DHgIDList_g0 =
1708 				    (node_dhc->auth_cfg.dh_group_priority[0]);
1709 				break;
1710 			case 3:
1711 				ap1->params.DHgIDList_g2 =
1712 				    (node_dhc->auth_cfg.dh_group_priority[2]);
1713 				ap1->params.DHgIDList_g1 =
1714 				    (node_dhc->auth_cfg.dh_group_priority[1]);
1715 				ap1->params.DHgIDList_g0 =
1716 				    (node_dhc->auth_cfg.dh_group_priority[0]);
1717 				break;
1718 			case 2:
1719 				ap1->params.DHgIDList_g1 =
1720 				    (node_dhc->auth_cfg.dh_group_priority[1]);
1721 				ap1->params.DHgIDList_g0 =
1722 				    (node_dhc->auth_cfg.dh_group_priority[0]);
1723 				break;
1724 			case 1:
1725 				ap1->params.DHgIDList_g0 =
1726 				    (node_dhc->auth_cfg.dh_group_priority[0]);
1727 				break;
1728 			}
1729 		} else {
1730 			ap2->tran_id =
1731 			    LE_SWAP32(node_dhc->nlp_auth_tranid_rsp);
1732 
1733 			ap2->params.name_tag = AUTH_NAME_ID;
1734 			ap2->params.name_len = AUTH_NAME_LEN;
1735 			bcopy((void *) &port->wwpn,
1736 			    (void *) &ap2->params.nodeName, sizeof (NAME_TYPE));
1737 			ap2->params.proto_num = AUTH_PROTO_NUM;
1738 			ap2->params.para_len = LE_SWAP32(para_len);
1739 			ap2->params.proto_id = AUTH_DHCHAP;
1740 			ap2->params.HashList_tag = HASH_LIST_TAG;
1741 			ap2->params.HashList_wcnt = LE_SWAP16(hash_wcnt);
1742 			ap2->params.HashList_value1 =
1743 			    (node_dhc->auth_cfg.hash_priority[0]);
1744 			ap2->params.HashList_value2 =
1745 			    (node_dhc->auth_cfg.hash_priority[1]);
1746 
1747 			ap2->params.DHgIDList_tag = DHGID_LIST_TAG;
1748 			ap2->params.DHgIDList_wnt = LE_SWAP16(dhgp_wcnt);
1749 
1750 			switch (dhgp_wcnt) {
1751 			case 5:
1752 				ap2->params.DHgIDList_g4 =
1753 				    (node_dhc->auth_cfg.dh_group_priority[4]);
1754 				ap2->params.DHgIDList_g3 =
1755 				    (node_dhc->auth_cfg.dh_group_priority[3]);
1756 				ap2->params.DHgIDList_g2 =
1757 				    (node_dhc->auth_cfg.dh_group_priority[2]);
1758 				ap2->params.DHgIDList_g1 =
1759 				    (node_dhc->auth_cfg.dh_group_priority[1]);
1760 				ap2->params.DHgIDList_g0 =
1761 				    (node_dhc->auth_cfg.dh_group_priority[0]);
1762 				break;
1763 			case 4:
1764 				ap2->params.DHgIDList_g3 =
1765 				    (node_dhc->auth_cfg.dh_group_priority[3]);
1766 				ap2->params.DHgIDList_g2 =
1767 				    (node_dhc->auth_cfg.dh_group_priority[2]);
1768 				ap2->params.DHgIDList_g1 =
1769 				    (node_dhc->auth_cfg.dh_group_priority[1]);
1770 				ap2->params.DHgIDList_g0 =
1771 				    (node_dhc->auth_cfg.dh_group_priority[0]);
1772 				break;
1773 			case 3:
1774 				ap2->params.DHgIDList_g2 =
1775 				    (node_dhc->auth_cfg.dh_group_priority[2]);
1776 				ap2->params.DHgIDList_g1 =
1777 				    (node_dhc->auth_cfg.dh_group_priority[1]);
1778 				ap2->params.DHgIDList_g0 =
1779 				    (node_dhc->auth_cfg.dh_group_priority[0]);
1780 				break;
1781 			case 2:
1782 				ap2->params.DHgIDList_g1 =
1783 				    (node_dhc->auth_cfg.dh_group_priority[1]);
1784 				ap2->params.DHgIDList_g0 =
1785 				    (node_dhc->auth_cfg.dh_group_priority[0]);
1786 				break;
1787 			case 1:
1788 				ap2->params.DHgIDList_g0 =
1789 				    (node_dhc->auth_cfg.dh_group_priority[0]);
1790 				break;
1791 			}
1792 		}
1793 	} else {
1794 		if (num_hs == 1) {
1795 			null_ap1->tran_id =
1796 			    LE_SWAP32(node_dhc->nlp_auth_tranid_rsp);
1797 
1798 			null_ap1->params.name_tag = AUTH_NAME_ID;
1799 			null_ap1->params.name_len = AUTH_NAME_LEN;
1800 			bcopy((void *) &port->wwpn,
1801 			    (void *) &null_ap1->params.nodeName,
1802 			    sizeof (NAME_TYPE));
1803 			null_ap1->params.proto_num = AUTH_PROTO_NUM;
1804 			null_ap1->params.para_len = LE_SWAP32(0x00000014);
1805 			null_ap1->params.proto_id = AUTH_DHCHAP;
1806 			null_ap1->params.HashList_tag = HASH_LIST_TAG;
1807 			null_ap1->params.HashList_wcnt = LE_SWAP16(0x0001);
1808 			null_ap1->params.HashList_value1 =
1809 			    (node_dhc->auth_cfg.hash_priority[0]);
1810 			null_ap1->params.DHgIDList_tag = DHGID_LIST_TAG;
1811 			null_ap1->params.DHgIDList_wnt = LE_SWAP16(0x0001);
1812 			null_ap1->params.DHgIDList_g0 = 0x0;
1813 		} else {
1814 			null_ap2->tran_id =
1815 			    LE_SWAP32(node_dhc->nlp_auth_tranid_rsp);
1816 
1817 			null_ap2->params.name_tag = AUTH_NAME_ID;
1818 			null_ap2->params.name_len = AUTH_NAME_LEN;
1819 			bcopy((void *) &port->wwpn,
1820 			    (void *) &null_ap2->params.nodeName,
1821 			    sizeof (NAME_TYPE));
1822 			null_ap2->params.proto_num = AUTH_PROTO_NUM;
1823 			null_ap2->params.para_len = LE_SWAP32(0x00000018);
1824 			null_ap2->params.proto_id = AUTH_DHCHAP;
1825 
1826 			null_ap2->params.HashList_tag = HASH_LIST_TAG;
1827 			null_ap2->params.HashList_wcnt = LE_SWAP16(0x0002);
1828 			null_ap2->params.HashList_value1 =
1829 			    (node_dhc->auth_cfg.hash_priority[0]);
1830 			null_ap2->params.HashList_value2 =
1831 			    (node_dhc->auth_cfg.hash_priority[1]);
1832 
1833 			null_ap2->params.DHgIDList_tag = DHGID_LIST_TAG;
1834 			null_ap2->params.DHgIDList_wnt = LE_SWAP16(0x0001);
1835 			null_ap2->params.DHgIDList_g0 = 0x0;
1836 		}
1837 	}
1838 
1839 	pkt->pkt_comp = emlxs_cmpl_auth_negotiate_issue;
1840 
1841 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_debug_msg,
1842 	    "issue_auth_negotiate: %x flag=%d size=%d hash=%x,%x tid=%x,%x",
1843 	    ndlp->nlp_DID, flag, cmd_size,
1844 	    node_dhc->auth_cfg.hash_priority[0],
1845 	    node_dhc->auth_cfg.hash_priority[1],
1846 	    node_dhc->nlp_auth_tranid_rsp, node_dhc->nlp_auth_tranid_ini);
1847 
1848 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
1849 		emlxs_pkt_free(pkt);
1850 
1851 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
1852 		    "issue_auth_negotiate: Unable to send pkt. did=0x%x",
1853 		    ndlp->nlp_DID);
1854 
1855 		return (1);
1856 	}
1857 	return (0);
1858 
1859 } /* emlxs_issue_auth_negotiate() */
1860 
1861 
1862 
1863 /*
1864  * ! emlxs_cmpl_auth_negotiate_issue
1865  *
1866  * \pre \post \param   phba \param   cmdiocb \param   rspiocb \return  void
1867  *
1868  * \b Description: iocb_cmpl callback function.
1869  *
1870  */
1871 static void
emlxs_cmpl_auth_negotiate_issue(fc_packet_t * pkt)1872 emlxs_cmpl_auth_negotiate_issue(fc_packet_t *pkt)
1873 {
1874 	emlxs_port_t *port = pkt->pkt_ulp_private;
1875 	emlxs_buf_t *sbp;
1876 	NODELIST *ndlp;
1877 	emlxs_node_dhc_t *node_dhc;
1878 	uint32_t did;
1879 
1880 	did = pkt->pkt_cmd_fhdr.d_id;
1881 	sbp = (emlxs_buf_t *)pkt->pkt_fca_private;
1882 	ndlp = sbp->node;
1883 	node_dhc = &ndlp->node_dhc;
1884 
1885 	if (!ndlp) {
1886 		ndlp = emlxs_node_find_did(port, did, 1);
1887 	}
1888 	if (pkt->pkt_state != FC_PKT_SUCCESS) {
1889 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
1890 		    "cmpl_dhchap_negotiate_issue: 0x%x %x. Noretry.",
1891 		    did, pkt->pkt_state);
1892 	} else {
1893 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
1894 		    "cmpl_dhchap_negotiate_issue: did=0x%x. Succcess.",
1895 		    did);
1896 	}
1897 
1898 	if (ndlp) {
1899 		if (pkt->pkt_state == FC_PKT_SUCCESS) {
1900 			(void) emlxs_dhchap_state_machine(port, NULL, NULL,
1901 			    NULL, ndlp, NODE_EVENT_CMPL_AUTH_MSG);
1902 		} else {
1903 			emlxs_dhc_set_reauth_time(port, ndlp, DISABLE);
1904 
1905 			emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_FAILED,
1906 			    0, 0);
1907 
1908 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_debug_msg,
1909 			    "Reauth disabled. did=0x%x state=%x",
1910 			    ndlp->nlp_DID, node_dhc->state);
1911 
1912 			emlxs_dhc_auth_complete(port, ndlp, 1);
1913 		}
1914 	}
1915 	emlxs_pkt_free(pkt);
1916 
1917 	return;
1918 
1919 } /* emlxs_cmpl_auth_negotiate_issue */
1920 
1921 
1922 /*
1923  * ! emlxs_cmpl_auth_msg_auth_negotiate_issue
1924  *
1925  * \pre \post \param   port \param   CHANNEL * rp \param   arg \param   evt
1926  * \return  uint32_t \b Description:
1927  *
1928  * This routine is invoked when the host receive the solicited ACC/RJT ELS
1929  * cmd from an NxPort or FxPort that has received the ELS
1930  * AUTH Negotiate msg from the host. in case of RJT, Auth_Negotiate should
1931  * be retried in emlxs_cmpl_auth_negotiate_issue
1932  * call. in case of ACC, the host must be the initiator because its current
1933  * state could be "AUTH_NEGOTIATE_RCV" if it is the
1934  * responder. Then the next stat = AUTH_NEGOTIATE_CMPL_WAIT4NEXT
1935  */
1936 /* ARGSUSED */
1937 static uint32_t
emlxs_cmpl_auth_msg_auth_negotiate_issue(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)1938 emlxs_cmpl_auth_msg_auth_negotiate_issue(
1939 emlxs_port_t *port,
1940 /* CHANNEL * rp, */ void *arg1,
1941 /* IOCBQ * iocbq, */ void *arg2,
1942 /* MATCHMAP * mp, */ void *arg3,
1943 /* NODELIST * ndlp, */ void *arg4,
1944 uint32_t evt)
1945 {
1946 	NODELIST *ndlp = (NODELIST *)arg4;
1947 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
1948 
1949 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
1950 	    "cmpl_auth_msg_auth_negotiate_issue: did=0x%x",
1951 	    ndlp->nlp_DID);
1952 
1953 	/* start the emlxs_dhc_authrsp_timeout timer */
1954 	if (node_dhc->nlp_authrsp_tmo == 0) {
1955 		node_dhc->nlp_authrsp_tmo = DRV_TIME +
1956 		    node_dhc->auth_cfg.authentication_timeout;
1957 	}
1958 	/*
1959 	 * The next state should be
1960 	 * emlxs_rcv_auth_msg_auth_negotiate_cmpl_wait4next
1961 	 */
1962 	emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_NEGOTIATE_CMPL_WAIT4NEXT,
1963 	    0, 0);
1964 
1965 	return (node_dhc->state);
1966 
1967 } /* emlxs_cmpl_auth_msg_auth_negotiate_issue */
1968 
1969 
1970 
1971 /*
1972  * ! emlxs_rcv_auth_msg_auth_negotiate_issue
1973  *
1974  * \pre \post \param   phba \param   ndlp \param   arg \param   evt \return
1975  * uint32_t \b Description:
1976  *
1977  * This routine is supported for HBA in either auth initiator mode or
1978  * responder mode.
1979  *
1980  * This routine is invoked when the host receive an unsolicited ELS AUTH Msg
1981  * from an NxPort or FxPort to which the host has just
1982  * sent out an ELS AUTH negotiate msg. and the NxPort or FxPort also LS_ACC
1983  * to the host's AUTH_Negotiate msg.
1984  *
1985  * If this unsolicited ELS auth msg is from the FxPort or a NxPort with a
1986  * numerically lower WWPN, the host will be the winner in
1987  * this authentication transaction initiation phase, the host as the
1988  * initiator will send back ACC and then Auth_Reject message
1989  * with the Reason Code 'Logical Error' and Reason Code Explanation'
1990  * Authentication Transaction Already Started' and with the
1991  * current state unchanged and mark itself as auth_initiator.
1992  *
1993  * Otherwise, the host will be the responder that will reply to the received
1994  * AUTH_Negotiate message will ACC (or RJT?) and abort
1995  * its own transaction upon receipt of the AUTH_Reject message. The new state
1996  * will be "AUTH_NEGOTIATE_RCV" and mark the host as
1997  * auth_responder.
1998  */
1999 /* ARGSUSED */
2000 static uint32_t
emlxs_rcv_auth_msg_auth_negotiate_issue(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)2001 emlxs_rcv_auth_msg_auth_negotiate_issue(
2002 emlxs_port_t *port,
2003 /* CHANNEL * rp, */ void *arg1,
2004 /* IOCBQ * iocbq, */ void *arg2,
2005 /* MATCHMAP * mp, */ void *arg3,
2006 /* NODELIST * ndlp */ void *arg4,
2007 uint32_t evt)
2008 {
2009 	NODELIST *ndlp = (NODELIST *)arg4;
2010 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
2011 	IOCBQ *iocbq = (IOCBQ *) arg2;
2012 	uint8_t ReasonCode;
2013 	uint8_t ReasonCodeExplanation;
2014 
2015 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
2016 	    "rcv_auth_msg_auth_negotiate_issue: did=0x%x",
2017 	    ndlp->nlp_DID);
2018 
2019 	/* Anyway we accept it first and then send auth_reject */
2020 	(void) emlxs_els_reply(port, iocbq, ELS_CMD_ACC, ELS_CMD_AUTH, 0, 0);
2021 
2022 	/* host is always the initiator and it should win */
2023 	ReasonCode = AUTHRJT_LOGIC_ERR;
2024 	ReasonCodeExplanation = AUTHEXP_AUTHTRAN_STARTED;
2025 
2026 	emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_NEGOTIATE_ISSUE,
2027 	    ReasonCode, ReasonCodeExplanation);
2028 	(void) emlxs_issue_auth_reject(port, ndlp, 0, 0, ReasonCode,
2029 	    ReasonCodeExplanation);
2030 
2031 	return (node_dhc->state);
2032 
2033 } /* emlxs_rcv_auth_msg_auth_negotiate_issue */
2034 
2035 
2036 /*
2037  * ! emlxs_cmpl_dhchap_reply_issue
2038  *
2039  * \pre \post \param   phba \param   cmdiocb \param   rspiocb \return  void
2040  *
2041  * \b Description: iocb_cmpl callback function.
2042  *
2043  */
2044 static void
emlxs_cmpl_dhchap_reply_issue(fc_packet_t * pkt)2045 emlxs_cmpl_dhchap_reply_issue(fc_packet_t *pkt)
2046 {
2047 	emlxs_port_t *port = pkt->pkt_ulp_private;
2048 	emlxs_buf_t *sbp;
2049 	NODELIST *ndlp;
2050 	uint32_t did;
2051 
2052 	did = pkt->pkt_cmd_fhdr.d_id;
2053 	sbp = (emlxs_buf_t *)pkt->pkt_fca_private;
2054 	ndlp = sbp->node;
2055 
2056 	if (!ndlp) {
2057 		ndlp = emlxs_node_find_did(port, did, 1);
2058 	}
2059 	if (pkt->pkt_state != FC_PKT_SUCCESS) {
2060 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
2061 		    "cmpl_dhchap_reply_issue: 0x%x %x. No retry.",
2062 		    did, pkt->pkt_state);
2063 	} else {
2064 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
2065 		    "cmpl_dhchap_reply_issue: did=0x%x. Succcess.",
2066 		    did);
2067 	}
2068 
2069 	if (ndlp) {
2070 		if (pkt->pkt_state == FC_PKT_SUCCESS) {
2071 			(void) emlxs_dhchap_state_machine(port, NULL, NULL,
2072 			    NULL, ndlp, NODE_EVENT_CMPL_AUTH_MSG);
2073 		}
2074 	}
2075 	emlxs_pkt_free(pkt);
2076 
2077 	return;
2078 
2079 } /* emlxs_cmpl_dhchap_reply_issue */
2080 
2081 
2082 /*
2083  * arg: the AUTH_Negotiate payload from the initiator. payload_len: the
2084  * payload length
2085  *
2086  * We always send out the challenge parameter based on our preference
2087  * order configured on the host side no matter what perference
2088  * order looks like from auth_negotiate . In other words, if the host issue
2089  * the challenge the host will make the decision as to
2090  * what hash function, what dhgp_id is to be used.
2091  *
2092  * This challenge value should not be confused with the challenge value for
2093  * bi-dir as part of reply when host is the initiator.
2094  */
2095 /* ARGSUSED */
2096 uint32_t
emlxs_issue_dhchap_challenge(emlxs_port_t * port,NODELIST * ndlp,int retry,void * arg,uint32_t payload_len,uint32_t hash_id,uint32_t dhgp_id)2097 emlxs_issue_dhchap_challenge(
2098 	emlxs_port_t *port,
2099 	NODELIST *ndlp,
2100 	int retry,
2101 	void *arg,
2102 	uint32_t payload_len,
2103 	uint32_t hash_id,
2104 	uint32_t dhgp_id)
2105 {
2106 	emlxs_hba_t *hba = HBA;
2107 	fc_packet_t *pkt;
2108 	uint32_t cmd_size;
2109 	uint32_t rsp_size;
2110 	uint16_t cmdsize = 0;
2111 	uint8_t *pCmd;
2112 	emlxs_port_dhc_t *port_dhc = &port->port_dhc;
2113 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
2114 	DHCHAP_CHALL *chal;
2115 	uint8_t *tmp;
2116 	uint8_t random_number[20];
2117 	uint8_t dhval[256];
2118 	uint32_t dhval_len;
2119 	uint32_t tran_id;
2120 	BIG_ERR_CODE err = BIG_OK;
2121 
2122 	/*
2123 	 * we assume the HBAnyware should configure the driver the right
2124 	 * parameters for challenge. for now, we create our own challenge.
2125 	 */
2126 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
2127 	    "issue_dhchap_challenge: did=0x%x hashlist=[%x,%x,%x,%x]",
2128 	    ndlp->nlp_DID, node_dhc->auth_cfg.hash_priority[0],
2129 	    node_dhc->auth_cfg.hash_priority[1],
2130 	    node_dhc->auth_cfg.hash_priority[2],
2131 	    node_dhc->auth_cfg.hash_priority[3]);
2132 
2133 	/*
2134 	 * Here is my own challenge structure:
2135 	 *
2136 	 * 1: AUTH_MSG_HDR (12 bytes + 4 bytes + 8 bytes) 2: hasd_id (4
2137 	 * bytes) 3: dhgp_id (4 bytes) 4: cval_len (4 bytes) 5: cval
2138 	 * (20 bytes or 16 bytes: cval_len bytes) 6: dhval_len (4 bytes)
2139 	 * 7: dhval (dhval_len bytes) all these information should be stored
2140 	 * in port_dhc struct
2141 	 */
2142 	if (hash_id == AUTH_SHA1) {
2143 		cmdsize = (12 + 4 + 8) + (4 + 4 + 4) + 20 + 4;
2144 	} else if (hash_id == AUTH_MD5) {
2145 		cmdsize = (12 + 4 + 8) + (4 + 4 + 4) + 16 + 4;
2146 	} else {
2147 		return (1);
2148 	}
2149 
2150 
2151 	switch (dhgp_id) {
2152 	case GROUP_NULL:
2153 		break;
2154 
2155 	case GROUP_1024:
2156 		cmdsize += 128;
2157 		break;
2158 
2159 	case GROUP_1280:
2160 		cmdsize += 160;
2161 		break;
2162 
2163 	case GROUP_1536:
2164 		cmdsize += 192;
2165 		break;
2166 
2167 	case GROUP_2048:
2168 		cmdsize += 256;
2169 		break;
2170 
2171 	default:
2172 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
2173 		    "issue_dhchap_challenge: Invalid dhgp_id=0x%x",
2174 		    dhgp_id);
2175 		return (1);
2176 	}
2177 
2178 	cmd_size = cmdsize;
2179 	rsp_size = 4;
2180 
2181 	if ((pkt = emlxs_prep_els_fc_pkt(port, ndlp->nlp_DID, cmd_size,
2182 	    rsp_size,
2183 	    0, KM_NOSLEEP)) == NULL) {
2184 		return (1);
2185 	}
2186 	pCmd = (uint8_t *)pkt->pkt_cmd;
2187 
2188 	tmp = (uint8_t *)arg;
2189 	tmp += 8;
2190 	/* collect tran_id: this tran_id is set by the initiator */
2191 	tran_id = *(uint32_t *)tmp;
2192 
2193 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
2194 	    "issue_dhchap_challenge: 0x%x 0x%x 0x%x %d 0x%x 0x%x 0x%x",
2195 	    ndlp->nlp_DID, node_dhc->nlp_auth_tranid_ini,
2196 	    node_dhc->nlp_auth_tranid_rsp,
2197 	    cmdsize, tran_id, hash_id, dhgp_id);
2198 
2199 	/* store the tran_id : ndlp is the initiator */
2200 	node_dhc->nlp_auth_tranid_ini = LE_SWAP32(tran_id);
2201 
2202 	tmp += sizeof (uint32_t);
2203 
2204 	chal = (DHCHAP_CHALL *)pCmd;
2205 	chal->cnul.msg_hdr.auth_els_code = ELS_CMD_AUTH_CODE;
2206 	chal->cnul.msg_hdr.auth_els_flags = 0x0;
2207 	chal->cnul.msg_hdr.auth_msg_code = DHCHAP_CHALLENGE;
2208 	chal->cnul.msg_hdr.proto_version = 0x01;
2209 	chal->cnul.msg_hdr.msg_len = LE_SWAP32(cmdsize - 12);
2210 	chal->cnul.msg_hdr.tran_id = tran_id;
2211 	chal->cnul.msg_hdr.name_tag = (AUTH_NAME_ID);
2212 	chal->cnul.msg_hdr.name_len = (AUTH_NAME_LEN);
2213 
2214 	bcopy((void *) &port->wwpn,
2215 	    (void *) &chal->cnul.msg_hdr.nodeName, sizeof (NAME_TYPE));
2216 
2217 	chal->cnul.hash_id = hash_id;
2218 	chal->cnul.dhgp_id = dhgp_id;
2219 
2220 	chal->cnul.cval_len = ((chal->cnul.hash_id == AUTH_SHA1) ?
2221 	    LE_SWAP32(SHA1_LEN) : LE_SWAP32(MD5_LEN));
2222 
2223 	tmp = (uint8_t *)pCmd;
2224 	tmp += sizeof (DHCHAP_CHALL_NULL);
2225 
2226 #ifdef RAND
2227 	/* generate a random number as the challenge */
2228 	bzero(random_number, LE_SWAP32(chal->cnul.cval_len));
2229 
2230 	if (hba->rdn_flag == 1) {
2231 		emlxs_get_random_bytes(ndlp, random_number, 20);
2232 	} else {
2233 		(void) random_get_pseudo_bytes(random_number,
2234 		    LE_SWAP32(chal->cnul.cval_len));
2235 	}
2236 
2237 	/*
2238 	 * the host should store the challenge for later usage when later on
2239 	 * host get the reply msg, host needs to verify it by using its old
2240 	 * challenge, its private key as the input to the hash function. the
2241 	 * challenge as the random_number should be stored in
2242 	 * node_dhc->hrsp_cval[]
2243 	 */
2244 	if (ndlp->nlp_DID == FABRIC_DID) {
2245 		bcopy((void *) &random_number[0],
2246 		    (void *) &node_dhc->hrsp_cval[0],
2247 		    LE_SWAP32(chal->cnul.cval_len));
2248 		/* save another copy in partner's ndlp */
2249 		bcopy((void *) &random_number[0],
2250 		    (void *) &node_dhc->nlp_auth_misc.hrsp_cval[0],
2251 		    LE_SWAP32(chal->cnul.cval_len));
2252 	} else {
2253 		bcopy((void *) &random_number[0],
2254 		    (void *) &node_dhc->nlp_auth_misc.hrsp_cval[0],
2255 		    LE_SWAP32(chal->cnul.cval_len));
2256 	}
2257 	bcopy((void *) &random_number[0], (void *) tmp,
2258 	    LE_SWAP32(chal->cnul.cval_len));
2259 
2260 #endif	/* RAND */
2261 
2262 	/* for test only hardcode the challenge value */
2263 #ifdef MYRAND
2264 	if (ndlp->nlp_DID == FABRIC_DID) {
2265 		bcopy((void *) myrand, (void *) &node_dhc->hrsp_cval[0],
2266 		    LE_SWAP32(chal->cnul.cval_len));
2267 		/* save another copy in partner's ndlp */
2268 		bcopy((void *) myrand,
2269 		    (void *) &node_dhc->nlp_auth_misc.hrsp_cval[0],
2270 		    LE_SWAP32(chal->cnul.cval_len));
2271 	} else {
2272 		bcopy((void *) myrand,
2273 		    (void *) &node_dhc->nlp_auth_misc.hrsp_cval[0],
2274 		    LE_SWAP32(chal->cnul.cval_len));
2275 	}
2276 	bcopy((void *) myrand, (void *) tmp,
2277 	    LE_SWAP32(chal->cnul.cval_len));
2278 
2279 #endif	/* MYRAND */
2280 
2281 	if (ndlp->nlp_DID == FABRIC_DID) {
2282 		node_dhc->hrsp_cval_len = LE_SWAP32(chal->cnul.cval_len);
2283 		node_dhc->nlp_auth_misc.hrsp_cval_len =
2284 		    LE_SWAP32(chal->cnul.cval_len);
2285 	} else {
2286 		node_dhc->nlp_auth_misc.hrsp_cval_len =
2287 		    LE_SWAP32(chal->cnul.cval_len);
2288 	}
2289 
2290 	tmp += LE_SWAP32(chal->cnul.cval_len);
2291 
2292 	/*
2293 	 * we need another random number as the private key x which will be
2294 	 * used to compute the public key i.e. g^x mod p we intentionally set
2295 	 * the length of private key as the same length of challenge. we have
2296 	 * to store the private key in node_dhc->hrsp_priv_key[20].
2297 	 */
2298 #ifdef RAND
2299 
2300 	if (dhgp_id != GROUP_NULL) {
2301 
2302 		bzero(random_number, LE_SWAP32(chal->cnul.cval_len));
2303 
2304 		if (hba->rdn_flag == 1) {
2305 			emlxs_get_random_bytes(ndlp, random_number, 20);
2306 		} else {
2307 			(void) random_get_pseudo_bytes(random_number,
2308 			    LE_SWAP32(chal->cnul.cval_len));
2309 		}
2310 
2311 		if (ndlp->nlp_DID == FABRIC_DID) {
2312 			bcopy((void *) &random_number[0],
2313 			    (void *) node_dhc->hrsp_priv_key,
2314 			    LE_SWAP32(chal->cnul.cval_len));
2315 			bcopy((void *) &random_number[0],
2316 			    (void *) node_dhc->nlp_auth_misc.hrsp_priv_key,
2317 			    LE_SWAP32(chal->cnul.cval_len));
2318 		} else {
2319 			bcopy((void *) &random_number[0],
2320 			    (void *) node_dhc->nlp_auth_misc.hrsp_priv_key,
2321 			    LE_SWAP32(chal->cnul.cval_len));
2322 		}
2323 	}
2324 #endif	/* RAND */
2325 
2326 #ifdef MYRAND
2327 	if (dhgp_id != GROUP_NULL) {
2328 		/* For test only we hardcode the priv_key here */
2329 		bcopy((void *) myrand, (void *) node_dhc->hrsp_priv_key,
2330 		    LE_SWAP32(chal->cnul.cval_len));
2331 
2332 		if (ndlp->nlp_DID == FABRIC_DID) {
2333 			bcopy((void *) myrand,
2334 			    (void *) node_dhc->hrsp_priv_key,
2335 			    LE_SWAP32(chal->cnul.cval_len));
2336 			bcopy((void *) myrand,
2337 			    (void *) node_dhc->nlp_auth_misc.hrsp_priv_key,
2338 			    LE_SWAP32(chal->cnul.cval_len));
2339 		} else {
2340 			bcopy((void *) myrand,
2341 			    (void *) node_dhc->nlp_auth_misc.hrsp_priv_key,
2342 			    LE_SWAP32(chal->cnul.cval_len));
2343 		}
2344 	}
2345 #endif	/* MYRAND */
2346 
2347 	/* also store the hash function and dhgp_id being used in challenge. */
2348 	/* These information could be configurable through HBAnyware */
2349 	node_dhc->nlp_auth_hashid = hash_id;
2350 	node_dhc->nlp_auth_dhgpid = dhgp_id;
2351 
2352 	/*
2353 	 * generate the DH value DH value is g^x mod p  and it is also called
2354 	 * public key in which g is 2, x is the random number ontained above.
2355 	 * p is the dhgp3_pVal
2356 	 */
2357 
2358 #ifdef MYRAND
2359 
2360 	/* to get (g^x mod p) with x private key */
2361 	if (dhgp_id != GROUP_NULL) {
2362 
2363 		err = emlxs_BIGNUM_get_dhval(port, port_dhc, ndlp, dhval,
2364 		    &dhval_len, chal->cnul.dhgp_id,
2365 		    myrand, LE_SWAP32(chal->cnul.cval_len));
2366 
2367 		if (err != BIG_OK) {
2368 			emlxs_pkt_free(pkt);
2369 
2370 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
2371 			    "issue_dhchap_challenge: error. 0x%x",
2372 			    err);
2373 
2374 			return (1);
2375 		}
2376 		/* we are not going to use dhval and dhval_len */
2377 
2378 		/* *(uint32_t *)tmp = dhval_len; */
2379 		if (ndlp->nlp_DID == FABRIC_DID) {
2380 			*(uint32_t *)tmp =
2381 			    LE_SWAP32(node_dhc->hrsp_pubkey_len);
2382 		} else {
2383 			*(uint32_t *)tmp =
2384 			    LE_SWAP32(
2385 			    node_dhc->nlp_auth_misc.hrsp_pubkey_len);
2386 		}
2387 
2388 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
2389 		    "issue_dhchap_challenge: 0x%x: 0x%x 0x%x",
2390 		    ndlp->nlp_DID, *(uint32_t *)tmp, dhval_len);
2391 
2392 		tmp += sizeof (uint32_t);
2393 
2394 		if (ndlp->nlp_DID == FABRIC_DID) {
2395 			bcopy((void *) node_dhc->hrsp_pub_key, (void *)tmp,
2396 			    node_dhc->hrsp_pubkey_len);
2397 		} else {
2398 			bcopy((void *) node_dhc->nlp_auth_misc.hrsp_pub_key,
2399 			    (void *)tmp,
2400 			    node_dhc->nlp_auth_misc.hrsp_pubkey_len);
2401 		}
2402 	} else {
2403 		/* NULL DHCHAP */
2404 		*(uint32_t *)tmp = 0;
2405 	}
2406 
2407 #endif	/* MYRAND */
2408 
2409 #ifdef RAND
2410 
2411 	/* to get (g^x mod p) with x private key */
2412 	if (dhgp_id != GROUP_NULL) {
2413 
2414 		err = emlxs_BIGNUM_get_dhval(port, port_dhc, ndlp, dhval,
2415 		    &dhval_len, chal->cnul.dhgp_id,
2416 		    random_number, LE_SWAP32(chal->cnul.cval_len));
2417 
2418 		if (err != BIG_OK) {
2419 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
2420 			    "issue_dhchap_challenge: error. 0x%x",
2421 			    err);
2422 
2423 			emlxs_pkt_free(pkt);
2424 			return (1);
2425 		}
2426 		/* we are not going to use dhval and dhval_len */
2427 
2428 		/* *(uint32_t *)tmp = dhval_len; */
2429 		if (ndlp->nlp_DID == FABRIC_DID) {
2430 			*(uint32_t *)tmp =
2431 			    LE_SWAP32(node_dhc->hrsp_pubkey_len);
2432 		} else {
2433 			*(uint32_t *)tmp =
2434 			    LE_SWAP32(
2435 			    node_dhc->nlp_auth_misc.hrsp_pubkey_len);
2436 		}
2437 
2438 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
2439 		    "issue_dhchap_challenge: did=0x%x: pubkey_len=0x%x",
2440 		    ndlp->nlp_DID, *(uint32_t *)tmp);
2441 
2442 		tmp += sizeof (uint32_t);
2443 
2444 		if (ndlp->nlp_DID == FABRIC_DID) {
2445 			bcopy((void *) node_dhc->hrsp_pub_key, (void *)tmp,
2446 			    node_dhc->hrsp_pubkey_len);
2447 		} else {
2448 			bcopy((void *) node_dhc->nlp_auth_misc.hrsp_pub_key,
2449 			    (void *)tmp,
2450 			    node_dhc->nlp_auth_misc.hrsp_pubkey_len);
2451 		}
2452 	} else {
2453 		/* NULL DHCHAP */
2454 		*(uint32_t *)tmp = 0;
2455 	}
2456 
2457 #endif	/* RAND */
2458 
2459 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
2460 	    "issue_dhchap_challenge: 0x%x 0x%x 0x%x 0x%x 0x%x",
2461 	    ndlp->nlp_DID, node_dhc->nlp_auth_tranid_ini,
2462 	    node_dhc->nlp_auth_tranid_rsp,
2463 	    chal->cnul.hash_id, chal->cnul.dhgp_id);
2464 
2465 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
2466 	    "issue_dhchap_challenge: 0x%x 0x%x 0x%x 0x%x",
2467 	    ndlp->nlp_DID, tran_id, node_dhc->nlp_auth_hashid,
2468 	    node_dhc->nlp_auth_dhgpid);
2469 
2470 	pkt->pkt_comp = emlxs_cmpl_dhchap_challenge_issue;
2471 
2472 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
2473 		emlxs_pkt_free(pkt);
2474 
2475 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
2476 		    "issue_dhchap_challenge: Unable to send fc packet.");
2477 
2478 		return (1);
2479 	}
2480 	return (0);
2481 
2482 } /* emlxs_issue_dhchap_challenge */
2483 
2484 
2485 /*
2486  * DHCHAP_Reply msg
2487  */
2488 /* ARGSUSED */
2489 uint32_t
emlxs_issue_dhchap_reply(emlxs_port_t * port,NODELIST * ndlp,int retry,uint32_t * arg1,uint8_t * dhval,uint32_t dhval_len,uint8_t * arg2,uint32_t arg2_len)2490 emlxs_issue_dhchap_reply(
2491 	emlxs_port_t *port,
2492 	NODELIST *ndlp,
2493 	int retry,
2494 	uint32_t *arg1, /* response */
2495 	uint8_t *dhval,
2496 	uint32_t dhval_len,
2497 	uint8_t *arg2,	/* random number */
2498 	uint32_t arg2_len)
2499 {
2500 	fc_packet_t *pkt;
2501 	uint32_t cmd_size;
2502 	uint32_t rsp_size;
2503 	uint16_t cmdsize = 0;
2504 	DHCHAP_REPLY_HDR *ap;
2505 	uint8_t *pCmd;
2506 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
2507 
2508 	/* Header size */
2509 	cmdsize = sizeof (DHCHAP_REPLY_HDR);
2510 
2511 	/* Rsp value len size (4) + Response value size */
2512 	if (ndlp->nlp_DID == FABRIC_DID) {
2513 		if (node_dhc->hash_id == AUTH_MD5) {
2514 			cmdsize += 4 + MD5_LEN;
2515 		}
2516 		if (node_dhc->hash_id == AUTH_SHA1) {
2517 			cmdsize += 4 + SHA1_LEN;
2518 		}
2519 	} else {
2520 		if (node_dhc->nlp_auth_hashid == AUTH_MD5) {
2521 			cmdsize += 4 + MD5_LEN;
2522 		}
2523 		if (node_dhc->nlp_auth_hashid == AUTH_SHA1) {
2524 			cmdsize += 4 + SHA1_LEN;
2525 		}
2526 	}
2527 
2528 	/* DH value len size (4) + DH value size */
2529 	if (ndlp->nlp_DID == FABRIC_DID) {
2530 		switch (node_dhc->dhgp_id) {
2531 		case GROUP_NULL:
2532 
2533 			break;
2534 
2535 		case GROUP_1024:
2536 		case GROUP_1280:
2537 		case GROUP_1536:
2538 		case GROUP_2048:
2539 		default:
2540 			break;
2541 		}
2542 	}
2543 
2544 	cmdsize += 4 + dhval_len;
2545 
2546 	/* Challenge value len size (4) + Challenge value size */
2547 	if (node_dhc->auth_cfg.bidirectional == 0) {
2548 		cmdsize += 4;
2549 	} else {
2550 		if (ndlp->nlp_DID == FABRIC_DID) {
2551 			cmdsize += 4 + ((node_dhc->hash_id == AUTH_MD5) ?
2552 			    MD5_LEN : SHA1_LEN);
2553 		} else {
2554 			cmdsize += 4 +
2555 			    ((node_dhc->nlp_auth_hashid == AUTH_MD5) ? MD5_LEN :
2556 			    SHA1_LEN);
2557 		}
2558 	}
2559 
2560 	cmd_size = cmdsize;
2561 	rsp_size = 4;
2562 
2563 	if ((pkt = emlxs_prep_els_fc_pkt(port, ndlp->nlp_DID, cmd_size,
2564 	    rsp_size, 0, KM_NOSLEEP)) == NULL) {
2565 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
2566 		    "issue_dhchap_reply failed: did=0x%x size=%x,%x",
2567 		    ndlp->nlp_DID, cmd_size, rsp_size);
2568 
2569 		return (1);
2570 	}
2571 	pCmd = (uint8_t *)pkt->pkt_cmd;
2572 
2573 	ap = (DHCHAP_REPLY_HDR *)pCmd;
2574 	ap->auth_els_code = ELS_CMD_AUTH_CODE;
2575 	ap->auth_els_flags = 0x0;
2576 	ap->auth_msg_code = DHCHAP_REPLY;
2577 	ap->proto_version = 0x01;
2578 	ap->msg_len = LE_SWAP32(cmdsize - sizeof (DHCHAP_REPLY_HDR));
2579 	ap->tran_id = LE_SWAP32(node_dhc->nlp_auth_tranid_rsp);
2580 
2581 	pCmd = (uint8_t *)(pCmd + sizeof (DHCHAP_REPLY_HDR));
2582 
2583 	if (ndlp->nlp_DID == FABRIC_DID) {
2584 		if (node_dhc->hash_id == AUTH_MD5) {
2585 			*(uint32_t *)pCmd = LE_SWAP32(MD5_LEN);
2586 		} else {
2587 			*(uint32_t *)pCmd = LE_SWAP32(SHA1_LEN);
2588 		}
2589 	} else {
2590 		if (node_dhc->nlp_auth_hashid == AUTH_MD5) {
2591 			*(uint32_t *)pCmd = LE_SWAP32(MD5_LEN);
2592 		} else {
2593 			*(uint32_t *)pCmd = LE_SWAP32(SHA1_LEN);
2594 		}
2595 	}
2596 
2597 	pCmd = (uint8_t *)(pCmd + 4);
2598 
2599 	if (ndlp->nlp_DID == FABRIC_DID) {
2600 		if (node_dhc->hash_id == AUTH_MD5) {
2601 			bcopy((void *)arg1, pCmd, MD5_LEN);
2602 			pCmd = (uint8_t *)(pCmd + MD5_LEN);
2603 		} else {
2604 			bcopy((void *)arg1, (void *)pCmd, SHA1_LEN);
2605 
2606 			pCmd = (uint8_t *)(pCmd + SHA1_LEN);
2607 		}
2608 	} else {
2609 		if (node_dhc->nlp_auth_hashid == AUTH_MD5) {
2610 			bcopy((void *)arg1, pCmd, MD5_LEN);
2611 			pCmd = (uint8_t *)(pCmd + MD5_LEN);
2612 		} else {
2613 			bcopy((void *)arg1, (void *)pCmd, SHA1_LEN);
2614 			pCmd = (uint8_t *)(pCmd + SHA1_LEN);
2615 		}
2616 	}
2617 
2618 	*(uint32_t *)pCmd = LE_SWAP32(dhval_len);
2619 
2620 	if (dhval_len != 0) {
2621 		pCmd = (uint8_t *)(pCmd + 4);
2622 
2623 		switch (node_dhc->dhgp_id) {
2624 		case GROUP_NULL:
2625 
2626 			break;
2627 
2628 		case GROUP_1024:
2629 		case GROUP_1280:
2630 		case GROUP_1536:
2631 		case GROUP_2048:
2632 		default:
2633 			break;
2634 		}
2635 		/* elx_bcopy((void *)dhval, (void *)pCmd, dhval_len); */
2636 		/*
2637 		 * The new DH parameter (g^y mod p) is stored in
2638 		 * node_dhc->pub_key
2639 		 */
2640 		/* pubkey_len should be equal to dhval_len */
2641 
2642 		if (ndlp->nlp_DID == FABRIC_DID) {
2643 			bcopy((void *) node_dhc->pub_key, (void *)pCmd,
2644 			    node_dhc->pubkey_len);
2645 		} else {
2646 			bcopy((void *) node_dhc->nlp_auth_misc.pub_key,
2647 			    (void *)pCmd,
2648 			    node_dhc->nlp_auth_misc.pubkey_len);
2649 		}
2650 		pCmd = (uint8_t *)(pCmd + dhval_len);
2651 	} else
2652 		pCmd = (uint8_t *)(pCmd + 4);
2653 
2654 	if (node_dhc->auth_cfg.bidirectional == 0) {
2655 		*(uint32_t *)pCmd = 0x0;
2656 	} else {
2657 		if (ndlp->nlp_DID == FABRIC_DID) {
2658 			if (node_dhc->hash_id == AUTH_MD5) {
2659 				*(uint32_t *)pCmd = LE_SWAP32(MD5_LEN);
2660 				pCmd = (uint8_t *)(pCmd + 4);
2661 				bcopy((void *)arg2, (void *)pCmd, arg2_len);
2662 			} else if (node_dhc->hash_id == AUTH_SHA1) {
2663 				*(uint32_t *)pCmd = LE_SWAP32(SHA1_LEN);
2664 				pCmd = (uint8_t *)(pCmd + 4);
2665 				/* store the challenge */
2666 				bcopy((void *)arg2, (void *)pCmd, arg2_len);
2667 			}
2668 		} else {
2669 			if (node_dhc->nlp_auth_hashid == AUTH_MD5) {
2670 				*(uint32_t *)pCmd = LE_SWAP32(MD5_LEN);
2671 				pCmd = (uint8_t *)(pCmd + 4);
2672 				bcopy((void *)arg2, (void *)pCmd, arg2_len);
2673 			} else if (node_dhc->nlp_auth_hashid == AUTH_SHA1) {
2674 				*(uint32_t *)pCmd = LE_SWAP32(SHA1_LEN);
2675 				pCmd = (uint8_t *)(pCmd + 4);
2676 				bcopy((void *)arg2, (void *)pCmd, arg2_len);
2677 			}
2678 		}
2679 	}
2680 
2681 	pkt->pkt_comp = emlxs_cmpl_dhchap_reply_issue;
2682 
2683 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
2684 	    "issue_dhchap_reply: did=0x%x  (%x,%x,%x,%x,%x,%x)",
2685 	    ndlp->nlp_DID, dhval_len, arg2_len, cmdsize,
2686 	    node_dhc->hash_id, node_dhc->nlp_auth_hashid,
2687 	    LE_SWAP32(ap->tran_id));
2688 
2689 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
2690 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
2691 		    "issue_dhchap_reply failed: Unable to send packet.");
2692 
2693 		emlxs_pkt_free(pkt);
2694 
2695 		return (1);
2696 	}
2697 	return (0);
2698 
2699 } /* emlxs_issue_dhchap_reply */
2700 
2701 
2702 
2703 /*
2704  * ! emlxs_rcv_auth_msg_auth_negotiate_cmpl_wait4next
2705  *
2706  * \pre \post \param   phba \param   ndlp \param   arg \param   evt \return
2707  * uint32_t \b Description:
2708  *
2709  * This routine is invoked when the host received an unsolicted ELS AUTH MSG
2710  * from an NxPort or FxPort which already replied (ACC)
2711  * the ELS AUTH_Negotiate msg from the host. if msg is DHCHAP_Chellenge,
2712  * based on the msg content (DHCHAP computation etc.,)
2713  * the host send back ACC and 1. send back AUTH_Reject and set next state =
2714  * NPR_NODE or 2. send back DHCHAP_Reply msg and set
2715  * next state = DHCHAP_REPLY_ISSUE for bi-directional, the DHCHAP_Reply
2716  * includes challenge from host. for uni-directional, no
2717  * more challenge. if msg is AUTH_Reject or anything else, host send back
2718  * ACC and set next state = NPR_NODE. And based on the
2719  * reject code, host may need to retry negotiate with NULL DH only
2720  *
2721  * If the msg is AUTH_ELS cmd, cancel the nlp_authrsp_timeout timer immediately.
2722  *
2723  */
2724 /* ARGSUSED */
2725 static uint32_t
emlxs_rcv_auth_msg_auth_negotiate_cmpl_wait4next(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)2726 emlxs_rcv_auth_msg_auth_negotiate_cmpl_wait4next(
2727 emlxs_port_t *port,
2728 /* CHANNEL * rp, */ void *arg1,
2729 /* IOCBQ * iocbq, */ void *arg2,
2730 /* MATCHMAP * mp, */ void *arg3,
2731 /* NODELIST * ndlp */ void *arg4,
2732 uint32_t evt)
2733 {
2734 	emlxs_hba_t *hba = HBA;
2735 	emlxs_port_dhc_t *port_dhc = &port->port_dhc;
2736 	IOCBQ *iocbq = (IOCBQ *)arg2;
2737 	MATCHMAP *mp = (MATCHMAP *)arg3;
2738 	NODELIST *ndlp = (NODELIST *)arg4;
2739 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
2740 	uint8_t *bp;
2741 	uint32_t *lp;
2742 	DHCHAP_CHALL_NULL *ncval;
2743 	uint16_t namelen;
2744 	uint32_t dhvallen;
2745 	uint8_t *tmp;
2746 	uint8_t ReasonCode;
2747 	uint8_t ReasonCodeExplanation;
2748 
2749 	union challenge_val un_cval;
2750 
2751 	uint8_t *dhval = NULL;
2752 	uint8_t random_number[20];	/* for both SHA1 and MD5 */
2753 	uint32_t *arg5 = NULL;	/* response */
2754 	uint32_t tran_id;	/* Transaction Identifier */
2755 	uint32_t arg2len = 0;	/* len of new challenge for bidir auth */
2756 
2757 	AUTH_RJT *rjt;
2758 
2759 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
2760 	    "rcv_auth_msg_auth_negotiate_cmpl_wait4next: did=0x%x",
2761 	    ndlp->nlp_DID);
2762 
2763 	emlxs_dhc_state(port, ndlp, NODE_STATE_DHCHAP_REPLY_ISSUE, 0, 0);
2764 
2765 	(void) emlxs_els_reply(port, iocbq, ELS_CMD_ACC, ELS_CMD_AUTH, 0, 0);
2766 
2767 	bp = mp->virt;
2768 	lp = (uint32_t *)bp;
2769 
2770 	/*
2771 	 * 1. we process the DHCHAP_Challenge 2. ACC it first 3. based on the
2772 	 * result of 1 we DHCHAP_Reply or AUTH_Reject
2773 	 */
2774 	ncval = (DHCHAP_CHALL_NULL *)((uint8_t *)lp);
2775 
2776 	if (ncval->msg_hdr.auth_els_code != ELS_CMD_AUTH_CODE) {
2777 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
2778 		    "rcv_auth_msg_auth_negotiate_cmpl_wait4next: 0x%x %x",
2779 		    ndlp->nlp_DID, ncval->msg_hdr.auth_els_code);
2780 
2781 		/* need to setup reason code/reason explanation code  */
2782 		ReasonCode = AUTHRJT_FAILURE;
2783 		ReasonCodeExplanation = AUTHEXP_BAD_PROTOCOL;
2784 		goto AUTH_Reject;
2785 	}
2786 	if (ncval->msg_hdr.auth_msg_code == AUTH_REJECT) {
2787 		rjt = (AUTH_RJT *)((uint8_t *)lp);
2788 		ReasonCode = rjt->ReasonCode;
2789 		ReasonCodeExplanation = rjt->ReasonCodeExplanation;
2790 
2791 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
2792 		    "rcv_auth_msg_auth_negotiate_cmpl_wait4next: 0x%x.%x,%x",
2793 		    ndlp->nlp_DID, ReasonCode, ReasonCodeExplanation);
2794 
2795 		switch (ReasonCode) {
2796 		case AUTHRJT_LOGIC_ERR:
2797 			switch (ReasonCodeExplanation) {
2798 			case AUTHEXP_MECH_UNUSABLE:
2799 			case AUTHEXP_DHGROUP_UNUSABLE:
2800 			case AUTHEXP_HASHFUNC_UNUSABLE:
2801 				ReasonCode = AUTHRJT_LOGIC_ERR;
2802 				ReasonCodeExplanation = AUTHEXP_RESTART_AUTH;
2803 				break;
2804 
2805 			case AUTHEXP_RESTART_AUTH:
2806 				/*
2807 				 * Cancel the rsp timer if not cancelled yet.
2808 				 * and restart auth tran now.
2809 				 */
2810 				if (node_dhc->nlp_authrsp_tmo != 0) {
2811 					node_dhc->nlp_authrsp_tmo = 0;
2812 					node_dhc->nlp_authrsp_tmocnt = 0;
2813 				}
2814 				if (emlxs_dhc_auth_start(port, ndlp, NULL,
2815 				    NULL) != 0) {
2816 					EMLXS_MSGF(EMLXS_CONTEXT,
2817 					    &emlxs_fcsp_debug_msg,
2818 					    "Reauth timeout. failed. 0x%x %x",
2819 					    ndlp->nlp_DID, node_dhc->state);
2820 				}
2821 				return (node_dhc->state);
2822 
2823 			default:
2824 				ReasonCode = AUTHRJT_FAILURE;
2825 				ReasonCodeExplanation = AUTHEXP_AUTH_FAILED;
2826 				break;
2827 			}
2828 			break;
2829 
2830 		case AUTHRJT_FAILURE:
2831 		default:
2832 			ReasonCode = AUTHRJT_FAILURE;
2833 			ReasonCodeExplanation = AUTHEXP_AUTH_FAILED;
2834 			break;
2835 		}
2836 
2837 		goto AUTH_Reject;
2838 	}
2839 	if (ncval->msg_hdr.auth_msg_code != DHCHAP_CHALLENGE) {
2840 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
2841 		    "rcv_auth_msg_auth_negotiate_cmpl_wait4next: 0x%x.%x",
2842 		    ndlp->nlp_DID, ncval->msg_hdr.auth_msg_code);
2843 
2844 		ReasonCode = AUTHRJT_FAILURE;
2845 		ReasonCodeExplanation = AUTHEXP_BAD_PROTOCOL;
2846 		goto AUTH_Reject;
2847 	}
2848 	tran_id = ncval->msg_hdr.tran_id;
2849 
2850 	if (LE_SWAP32(tran_id) != node_dhc->nlp_auth_tranid_rsp) {
2851 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
2852 		    "rcv_auth_msg_auth_negotiate_cmpl_wait4next:0x%x %x!=%x",
2853 		    ndlp->nlp_DID, LE_SWAP32(tran_id),
2854 		    node_dhc->nlp_auth_tranid_rsp);
2855 
2856 		ReasonCode = AUTHRJT_FAILURE;
2857 		ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD;
2858 		goto AUTH_Reject;
2859 	}
2860 	node_dhc->nlp_authrsp_tmo = 0;
2861 
2862 	namelen = ncval->msg_hdr.name_len;
2863 
2864 	if (namelen == AUTH_NAME_LEN) {
2865 		/*
2866 		 * store another copy of wwn of fabric/or nport used in
2867 		 * AUTH_ELS cmd
2868 		 */
2869 		bcopy((void *)&ncval->msg_hdr.nodeName,
2870 		    (void *)&node_dhc->nlp_auth_wwn, sizeof (NAME_TYPE));
2871 	}
2872 	/* Collect the challenge value */
2873 	tmp = (uint8_t *)((uint8_t *)lp + sizeof (DHCHAP_CHALL_NULL));
2874 
2875 	if (ncval->hash_id == AUTH_MD5) {
2876 		if (ncval->cval_len != LE_SWAP32(MD5_LEN)) {
2877 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
2878 		    "rcv_auth_msg_auth_negotiate_cmpl_wait4next:0x%x.%x!=%x",
2879 		    ndlp->nlp_DID, ncval->cval_len, LE_SWAP32(MD5_LEN));
2880 
2881 			ReasonCode = AUTHRJT_FAILURE;
2882 			ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD;
2883 			goto AUTH_Reject;
2884 		}
2885 		bzero(un_cval.md5.val, sizeof (MD5_CVAL));
2886 		bcopy((void *)tmp, (void *)un_cval.md5.val,
2887 		    sizeof (MD5_CVAL));
2888 		tmp += sizeof (MD5_CVAL);
2889 
2890 		arg2len = MD5_LEN;
2891 
2892 	} else if (ncval->hash_id == AUTH_SHA1) {
2893 		if (ncval->cval_len != LE_SWAP32(SHA1_LEN)) {
2894 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
2895 		    "rcv_auth_msg_auth_negotiate_cmpl_wait4next: 0x%x %x!=%x",
2896 		    ndlp->nlp_DID, ncval->cval_len, LE_SWAP32(MD5_LEN));
2897 
2898 			ReasonCode = AUTHRJT_FAILURE;
2899 			ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD;
2900 			goto AUTH_Reject;
2901 		}
2902 		bzero(un_cval.sha1.val, sizeof (SHA1_CVAL));
2903 		bcopy((void *)tmp, (void *)un_cval.sha1.val,
2904 		    sizeof (SHA1_CVAL));
2905 		tmp += sizeof (SHA1_CVAL);
2906 
2907 		arg2len = SHA1_LEN;
2908 
2909 	} else {
2910 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
2911 	    "rcv_auth_msg_auth_negotiate_cmpl_wait4next: 0x%x %x",
2912 	    ndlp->nlp_DID, ncval->hash_id);
2913 
2914 		ReasonCode = AUTHRJT_FAILURE;
2915 		ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD;
2916 		goto AUTH_Reject;
2917 	}
2918 
2919 	/*
2920 	 * store hash_id for later usage : hash_id is set by responder in its
2921 	 * dhchap_challenge
2922 	 */
2923 	node_dhc->hash_id = ncval->hash_id;
2924 
2925 	/* always use this */
2926 	/* store another copy of the hash_id */
2927 	node_dhc->nlp_auth_hashid = ncval->hash_id;
2928 
2929 	/* store dhgp_id for later usage */
2930 	node_dhc->dhgp_id = ncval->dhgp_id;
2931 
2932 	/* store another copy of dhgp_id */
2933 	/* always use this */
2934 	node_dhc->nlp_auth_dhgpid = ncval->dhgp_id;
2935 
2936 	/*
2937 	 * ndlp->nlp_auth_hashid, nlp_auth_dhgpid store the hashid and dhgpid
2938 	 * when this very ndlp is the auth transaction responder (in other
2939 	 * words, responder means that this ndlp is send the host the
2940 	 * challenge. ndlp could be fffffe or another initiator or target
2941 	 * nport.
2942 	 */
2943 
2944 	dhvallen = *((uint32_t *)(tmp));
2945 
2946 	switch (ncval->dhgp_id) {
2947 	case GROUP_NULL:
2948 		/* null DHCHAP only */
2949 		if (LE_SWAP32(dhvallen) != 0) {
2950 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
2951 		    "rcv_auth_msg_auth_negotiate_cmpl_wait4next: 0x%x %x %x",
2952 		    ndlp->nlp_DID, ncval->dhgp_id, LE_SWAP32(dhvallen));
2953 
2954 			ReasonCode = AUTHRJT_FAILURE;
2955 			ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD;
2956 			goto AUTH_Reject;
2957 		}
2958 		break;
2959 
2960 	case GROUP_1024:
2961 	case GROUP_1280:
2962 	case GROUP_1536:
2963 	case GROUP_2048:
2964 		/* Collect the DH Value */
2965 		tmp += sizeof (uint32_t);
2966 
2967 		dhval = (uint8_t *)kmem_zalloc(LE_SWAP32(dhvallen),
2968 		    KM_NOSLEEP);
2969 		if (dhval == NULL) {
2970 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
2971 		    "rcv_auth_msg_auth_negotiate_cmpl_wait4next: 0x%x %x %x",
2972 		    ndlp->nlp_DID, ncval->dhgp_id, dhval);
2973 
2974 			ReasonCode = AUTHRJT_LOGIC_ERR;
2975 			ReasonCodeExplanation = AUTHEXP_RESTART_AUTH;
2976 			goto AUTH_Reject;
2977 		}
2978 		bcopy((void *)tmp, (void *)dhval, LE_SWAP32(dhvallen));
2979 		break;
2980 
2981 	default:
2982 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
2983 		    "rcv_auth_msg_auth_negotiate_cmpl_wait4next: 0x%x %x.",
2984 		    ndlp->nlp_DID, ncval->dhgp_id);
2985 
2986 		ReasonCode = AUTHRJT_FAILURE;
2987 		ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD;
2988 		goto AUTH_Reject;
2989 	}
2990 
2991 	/*
2992 	 * Calculate the hash value, hash function, DH group, secret etc.
2993 	 * could be stored in port_dhc.
2994 	 */
2995 
2996 	/* arg5 has the response with NULL or Full DH group support */
2997 	arg5 = (uint32_t *)emlxs_hash_rsp(port, port_dhc,
2998 	    ndlp, tran_id, un_cval, dhval, LE_SWAP32(dhvallen));
2999 
3000 	/* Or should check ndlp->auth_cfg..... */
3001 	if (node_dhc->auth_cfg.bidirectional == 1) {
3002 		/* get arg2 here */
3003 		/*
3004 		 * arg2 is the new challenge C2 from initiator if bi-dir auth
3005 		 * is supported
3006 		 */
3007 		bzero(&random_number, sizeof (random_number));
3008 
3009 		if (hba->rdn_flag == 1) {
3010 			emlxs_get_random_bytes(ndlp, random_number, 20);
3011 		} else {
3012 			(void) random_get_pseudo_bytes(random_number, arg2len);
3013 		}
3014 
3015 		/* cache it for later verification usage */
3016 		if (ndlp->nlp_DID == FABRIC_DID) {
3017 			bcopy((void *)&random_number[0],
3018 			    (void *)&node_dhc->bi_cval[0], arg2len);
3019 			node_dhc->bi_cval_len = arg2len;
3020 
3021 			/* save another copy in our partner's ndlp */
3022 			bcopy((void *)&random_number[0],
3023 			    (void *)&node_dhc->nlp_auth_misc.bi_cval[0],
3024 			    arg2len);
3025 			node_dhc->nlp_auth_misc.bi_cval_len = arg2len;
3026 		} else {
3027 			bcopy((void *)&random_number[0],
3028 			    (void *)&node_dhc->nlp_auth_misc.bi_cval[0],
3029 			    arg2len);
3030 			node_dhc->nlp_auth_misc.bi_cval_len = arg2len;
3031 		}
3032 	}
3033 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
3034 	    "rcv_auth_msg_auth_negotiate_cmpl_wait4next:0x%x(%x,%x,%x,%x,%x)",
3035 	    ndlp->nlp_DID, node_dhc->nlp_auth_tranid_rsp,
3036 	    node_dhc->nlp_auth_tranid_ini,
3037 	    ncval->hash_id, ncval->dhgp_id, dhvallen);
3038 
3039 	/* Issue ELS DHCHAP_Reply */
3040 	/*
3041 	 * arg1 has the response, arg2 has the new challenge if needed (g^y
3042 	 * mod p) is the pubkey: all are ready and to go
3043 	 */
3044 
3045 	/* return 0 success, otherwise failure */
3046 	if (emlxs_issue_dhchap_reply(port, ndlp, 0, arg5, dhval,
3047 	    LE_SWAP32(dhvallen),
3048 	    random_number, arg2len)) {
3049 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
3050 	    "rcv_auth_msg_auth_negotiate_cmpl_wait4next: 0x%x.failed.",
3051 	    ndlp->nlp_DID);
3052 
3053 		kmem_free(dhval, LE_SWAP32(dhvallen));
3054 		ReasonCode = AUTHRJT_LOGIC_ERR;
3055 		ReasonCodeExplanation = AUTHEXP_RESTART_AUTH;
3056 		goto AUTH_Reject;
3057 	}
3058 	return (node_dhc->state);
3059 
3060 AUTH_Reject:
3061 
3062 	emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_FAILED, ReasonCode,
3063 	    ReasonCodeExplanation);
3064 	(void) emlxs_issue_auth_reject(port, ndlp, 0, 0, ReasonCode,
3065 	    ReasonCodeExplanation);
3066 	emlxs_dhc_auth_complete(port, ndlp, 1);
3067 
3068 	return (node_dhc->state);
3069 
3070 } /* emlxs_rcv_auth_msg_auth_negotiate_cmpl_wait4next */
3071 
3072 
3073 /*
3074  * This routine should be set to emlxs_disc_neverdev
3075  *
3076  */
3077 /* ARGSUSED */
3078 static uint32_t
emlxs_cmpl_auth_msg_auth_negotiate_cmpl_wait4next(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)3079 emlxs_cmpl_auth_msg_auth_negotiate_cmpl_wait4next(
3080 emlxs_port_t	*port,
3081 /* CHANNEL * rp, */ void *arg1,
3082 /* IOCBQ * iocbq, */ void *arg2,
3083 /* MATCHMAP * mp, */ void *arg3,
3084 /* NODELIST * ndlp */ void *arg4,
3085 uint32_t evt)
3086 {
3087 	NODELIST *ndlp = (NODELIST *)arg4;
3088 
3089 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
3090 	    "cmpl_auth_msg_auth_negotiate_cmpl_wait4next.0x%x. Not iplted.",
3091 	    ndlp->nlp_DID);
3092 
3093 	return (0);
3094 } /* emlxs_cmpl_auth_msg_auth_negotiate_cmpl_wait4next() */
3095 
3096 
3097 /*
3098  * ! emlxs_rcv_auth_msg_dhchap_reply_issue
3099  *
3100  * This routine is invoked when the host received an unsolicited ELS AUTH
3101  * msg from an NxPort or FxPort into which the host has
3102  * sent an ELS DHCHAP_Reply msg. since the host is the initiator and the
3103  * AUTH transaction is in progress between host and the
3104  * NxPort or FxPort, as a result, the host will send back ACC and AUTH_Reject
3105  * and set the next state = NPR_NODE.
3106  *
3107  */
3108 /* ARGSUSED */
3109 static uint32_t
emlxs_rcv_auth_msg_dhchap_reply_issue(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)3110 emlxs_rcv_auth_msg_dhchap_reply_issue(
3111 emlxs_port_t *port,
3112 /* CHANNEL * rp, */ void *arg1,
3113 /* IOCBQ   * iocbq, */ void *arg2,
3114 /* MATCHMAP * mp, */ void *arg3,
3115 /* NODELIST * ndlp */ void *arg4,
3116 uint32_t evt)
3117 {
3118 	NODELIST *ndlp = (NODELIST *)arg4;
3119 
3120 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
3121 	    "rcv_auth_msg_dhchap_reply_issue called. 0x%x. Not implemented.",
3122 	    ndlp->nlp_DID);
3123 
3124 	return (0);
3125 
3126 } /* emlxs_rcv_auth_msg_dhchap_reply_issue */
3127 
3128 
3129 
3130 /*
3131  * ! emlxs_cmpl_auth_msg_dhchap_reply_issue
3132  *
3133  * This routine is invoked when
3134  * the host received a solicited ACC/RJT from ELS command from an NxPort
3135  * or FxPort that already received the ELS DHCHAP_Reply
3136  * msg from the host. in case of ACC, next state = DHCHAP_REPLY_CMPL_WAIT4NEXT
3137  * in case of RJT, next state = NPR_NODE
3138  */
3139 /* ARGSUSED */
3140 static uint32_t
emlxs_cmpl_auth_msg_dhchap_reply_issue(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)3141 emlxs_cmpl_auth_msg_dhchap_reply_issue(
3142 emlxs_port_t *port,
3143 /* CHANNEL  * rp, */ void *arg1,
3144 /* IOCBQ * iocbq, */ void *arg2,
3145 /* MATCHMAP * mp, */ void *arg3,
3146 /* NODELIST * ndlp */ void *arg4,
3147 uint32_t evt)
3148 {
3149 	NODELIST *ndlp = (NODELIST *) arg4;
3150 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
3151 
3152 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
3153 	    "cmpl_auth_msg_dhchap_reply_issue: did=0x%x",
3154 	    ndlp->nlp_DID);
3155 
3156 	/* start the emlxs_dhc_authrsp_timeout timer now */
3157 	if (node_dhc->nlp_authrsp_tmo == 0) {
3158 		node_dhc->nlp_authrsp_tmo = DRV_TIME +
3159 		    node_dhc->auth_cfg.authentication_timeout;
3160 	}
3161 	/*
3162 	 * The next state should be
3163 	 * emlxs_rcv_auth_msg_dhchap_reply_cmpl_wait4next
3164 	 */
3165 	emlxs_dhc_state(port, ndlp,
3166 	    NODE_STATE_DHCHAP_REPLY_CMPL_WAIT4NEXT, 0, 0);
3167 
3168 	return (node_dhc->state);
3169 
3170 } /* emlxs_cmpl_auth_msg_dhchap_reply_issue */
3171 
3172 
3173 
3174 /*
3175  * ! emlxs_rcv_auth_msg_dhchap_reply_cmpl_wait4next
3176  *
3177  * \pre \post \param   phba \param   ndlp \param   arg \param   evt \return
3178  * uint32_t \b Description: This rountine is invoked
3179  * when the host received an unsolicited ELS AUTH Msg from the NxPort or
3180  * FxPort that already sent ACC back to the host after
3181  * receipt of DHCHAP_Reply msg. In normal case, this unsolicited msg could
3182  * be DHCHAP_Success msg.
3183  *
3184  * if msg is ELS DHCHAP_Success, based on the payload, host send back ACC and 1.
3185  * for uni-directional, and set next state =
3186  * REG_LOGIN. 2. for bi-directional,  and host do some computations
3187  * (hash etc) and send back either DHCHAP_Success Msg and set
3188  * next state = DHCHAP_SUCCESS_ISSUE_WAIT4NEXT or AUTH_Reject and set next
3189  * state = NPR_NODE. if msg is ELS AUTH_Reject, then
3190  * send back ACC and set next state = NPR_NODE if msg is anything else, then
3191  * RJT and set next state = NPR_NODE
3192  */
3193 /* ARGSUSED */
3194 static uint32_t
emlxs_rcv_auth_msg_dhchap_reply_cmpl_wait4next(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)3195 emlxs_rcv_auth_msg_dhchap_reply_cmpl_wait4next(
3196 emlxs_port_t *port,
3197 /* CHANNEL * rp, */ void *arg1,
3198 /* IOCBQ * iocbq, */ void *arg2,
3199 /* MATCHMAP * mp, */ void *arg3,
3200 /* NODELIST * ndlp */ void *arg4,
3201 uint32_t evt)
3202 {
3203 	emlxs_port_dhc_t *port_dhc = &port->port_dhc;
3204 	IOCBQ *iocbq = (IOCBQ *)arg2;
3205 	MATCHMAP *mp = (MATCHMAP *)arg3;
3206 	NODELIST *ndlp = (NODELIST *)arg4;
3207 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
3208 	uint8_t *bp;
3209 	uint32_t *lp;
3210 	DHCHAP_SUCCESS_HDR *dh_success;
3211 	uint8_t *tmp;
3212 	uint8_t rsp_size;
3213 	AUTH_RJT *auth_rjt;
3214 	uint32_t tran_id;
3215 	uint32_t *hash_val;
3216 	union challenge_val un_cval;
3217 	uint8_t ReasonCode;
3218 	uint8_t ReasonCodeExplanation;
3219 	char info[64];
3220 
3221 	bp = mp->virt;
3222 	lp = (uint32_t *)bp;
3223 
3224 	/*
3225 	 * 1. we process the DHCHAP_Success or AUTH_Reject 2. ACC it first 3.
3226 	 * based on the result of 1 we goto the next stage SCR etc.
3227 	 */
3228 
3229 	/* sp = (SERV_PARM *)((uint8_t *)lp + sizeof(uint32_t)); */
3230 	dh_success = (DHCHAP_SUCCESS_HDR *)((uint8_t *)lp);
3231 
3232 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
3233 	    "rcv_auth_msg_dhchap_reply_cmpl_wait4next: 0x%x 0x%x 0x%x",
3234 	    ndlp->nlp_DID, dh_success->auth_els_code,
3235 	    dh_success->auth_msg_code);
3236 
3237 	node_dhc->nlp_authrsp_tmo = 0;
3238 
3239 	(void) emlxs_els_reply(port, iocbq, ELS_CMD_ACC, ELS_CMD_AUTH, 0, 0);
3240 
3241 	if (dh_success->auth_msg_code == AUTH_REJECT) {
3242 		/* ACC it and retry etc.  */
3243 		auth_rjt = (AUTH_RJT *) dh_success;
3244 		ReasonCode = auth_rjt->ReasonCode;
3245 		ReasonCodeExplanation = auth_rjt->ReasonCodeExplanation;
3246 
3247 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
3248 	    "rcv_auth_msg_dhchap_reply_cmpl_wait4next: 0x%x.(%x,%x)",
3249 	    ndlp->nlp_DID, ReasonCode, ReasonCodeExplanation);
3250 
3251 		switch (ReasonCode) {
3252 		case AUTHRJT_LOGIC_ERR:
3253 			switch (ReasonCodeExplanation) {
3254 			case AUTHEXP_MECH_UNUSABLE:
3255 			case AUTHEXP_DHGROUP_UNUSABLE:
3256 			case AUTHEXP_HASHFUNC_UNUSABLE:
3257 				ReasonCode = AUTHRJT_LOGIC_ERR;
3258 				ReasonCodeExplanation = AUTHEXP_RESTART_AUTH;
3259 				break;
3260 
3261 			case AUTHEXP_RESTART_AUTH:
3262 				/*
3263 				 * Cancel the rsp timer if not cancelled yet.
3264 				 * and restart auth tran now.
3265 				 */
3266 				if (node_dhc->nlp_authrsp_tmo != 0) {
3267 					node_dhc->nlp_authrsp_tmo = 0;
3268 					node_dhc->nlp_authrsp_tmocnt = 0;
3269 				}
3270 				if (emlxs_dhc_auth_start(port, ndlp,
3271 				    NULL, NULL) != 0) {
3272 					EMLXS_MSGF(EMLXS_CONTEXT,
3273 					    &emlxs_fcsp_debug_msg,
3274 					    "Reauth timeout.failed. 0x%x %x",
3275 					    ndlp->nlp_DID, node_dhc->state);
3276 				}
3277 				return (node_dhc->state);
3278 
3279 			default:
3280 				ReasonCode = AUTHRJT_FAILURE;
3281 				ReasonCodeExplanation = AUTHEXP_AUTH_FAILED;
3282 				break;
3283 			}
3284 			break;
3285 
3286 		case AUTHRJT_FAILURE:
3287 		default:
3288 			ReasonCode = AUTHRJT_FAILURE;
3289 			ReasonCodeExplanation = AUTHEXP_AUTH_FAILED;
3290 			emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_FAILED,
3291 			    ReasonCode, ReasonCodeExplanation);
3292 			goto out;
3293 		}
3294 
3295 		goto AUTH_Reject;
3296 	}
3297 	if (dh_success->auth_msg_code == DHCHAP_SUCCESS) {
3298 
3299 		/* Verify the tran_id */
3300 		tran_id = dh_success->tran_id;
3301 
3302 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
3303 	    "rcv_auth_msg_dhchap_reply_cmpl_wait4next: 0x%x 0x%x 0x%x 0x%x",
3304 	    ndlp->nlp_DID, LE_SWAP32(tran_id),
3305 	    node_dhc->nlp_auth_tranid_rsp,
3306 	    node_dhc->nlp_auth_tranid_ini);
3307 
3308 		if (LE_SWAP32(tran_id) != node_dhc->nlp_auth_tranid_rsp) {
3309 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
3310 		    "rcv_auth_msg_dhchap_reply_cmpl_wait4next:0x%x %x!=%x",
3311 		    ndlp->nlp_DID, LE_SWAP32(tran_id),
3312 		    node_dhc->nlp_auth_tranid_rsp);
3313 
3314 			ReasonCode = AUTHRJT_FAILURE;
3315 			ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD;
3316 			goto AUTH_Reject;
3317 		}
3318 		if (node_dhc->auth_cfg.bidirectional == 0) {
3319 			node_dhc->flag |=
3320 			    (NLP_REMOTE_AUTH | NLP_SET_REAUTH_TIME);
3321 
3322 			emlxs_dhc_state(port, ndlp,
3323 			    NODE_STATE_AUTH_SUCCESS, 0, 0);
3324 			emlxs_log_auth_event(port, ndlp,
3325 			    "rcv_auth_msg_dhchap_reply_cmpl_wait4next",
3326 			    "Host-initiated-unidir-auth-success");
3327 			emlxs_dhc_auth_complete(port, ndlp, 0);
3328 		} else {
3329 			/* bidir auth needed */
3330 			/* if (LE_SWAP32(dh_success->msg_len) > 4) { */
3331 
3332 			tmp = (uint8_t *)((uint8_t *)lp);
3333 			tmp += 8;
3334 			tran_id = *(uint32_t *)tmp;
3335 			tmp += 4;
3336 			rsp_size = *(uint32_t *)tmp;
3337 			tmp += 4;
3338 
3339 			/* tmp has the response from responder */
3340 
3341 			/*
3342 			 * node_dhc->bi_cval has the bidir challenge value
3343 			 * from initiator
3344 			 */
3345 
3346 			if (LE_SWAP32(rsp_size) == 16) {
3347 				bzero(un_cval.md5.val, LE_SWAP32(rsp_size));
3348 				if (ndlp->nlp_DID == FABRIC_DID)
3349 					bcopy((void *)node_dhc->bi_cval,
3350 					    (void *)un_cval.md5.val,
3351 					    LE_SWAP32(rsp_size));
3352 				else
3353 				bcopy(
3354 				    (void *)node_dhc->nlp_auth_misc.bi_cval,
3355 				    (void *)un_cval.md5.val,
3356 				    LE_SWAP32(rsp_size));
3357 
3358 			} else if (LE_SWAP32(rsp_size) == 20) {
3359 
3360 				bzero(un_cval.sha1.val, LE_SWAP32(rsp_size));
3361 				if (ndlp->nlp_DID == FABRIC_DID)
3362 					bcopy((void *)node_dhc->bi_cval,
3363 					    (void *)un_cval.sha1.val,
3364 					    LE_SWAP32(rsp_size));
3365 				else
3366 				bcopy(
3367 				    (void *)node_dhc->nlp_auth_misc.bi_cval,
3368 				    (void *)un_cval.sha1.val,
3369 				    LE_SWAP32(rsp_size));
3370 			}
3371 			/* verify the response */
3372 			/* NULL DHCHAP works for now */
3373 			/* for DH group as well */
3374 
3375 			/*
3376 			 * Cai2 = H (C2 || ((g^x mod p)^y mod p) ) = H (C2 ||
3377 			 * (g^xy mod p) )
3378 			 *
3379 			 * R = H (Ti || Km || Cai2) R ?= R2
3380 			 */
3381 			hash_val = emlxs_hash_vrf(port, port_dhc, ndlp,
3382 			    tran_id, un_cval);
3383 
3384 			if (bcmp((void *)tmp, (void *)hash_val,
3385 			    LE_SWAP32(rsp_size))) {
3386 				if (hash_val != NULL) {
3387 					/* not identical */
3388 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
3389 	    "rcv_auth_msg_dhchap_reply_cmpl_wait4next: 0x%x.failed. %x",
3390 	    ndlp->nlp_DID, *(uint32_t *)hash_val);
3391 				}
3392 				ReasonCode = AUTHRJT_FAILURE;
3393 				ReasonCodeExplanation = AUTHEXP_AUTH_FAILED;
3394 				goto AUTH_Reject;
3395 			}
3396 			emlxs_dhc_state(port, ndlp,
3397 			    NODE_STATE_DHCHAP_SUCCESS_ISSUE_WAIT4NEXT, 0, 0);
3398 
3399 			/* send out DHCHAP_SUCCESS */
3400 			(void) emlxs_issue_dhchap_success(port, ndlp, 0, 0);
3401 		}
3402 	}
3403 	return (node_dhc->state);
3404 
3405 AUTH_Reject:
3406 
3407 	emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_FAILED,
3408 	    ReasonCode, ReasonCodeExplanation);
3409 	(void) emlxs_issue_auth_reject(port, ndlp, 0, 0, ReasonCode,
3410 	    ReasonCodeExplanation);
3411 	emlxs_dhc_auth_complete(port, ndlp, 1);
3412 
3413 	return (node_dhc->state);
3414 out:
3415 	(void) snprintf(info, sizeof (info),
3416 	    "Auth Failed: ReasonCode=0x%x, ReasonCodeExplanation=0x%x",
3417 	    ReasonCode, ReasonCodeExplanation);
3418 
3419 	emlxs_log_auth_event(port, ndlp,
3420 	    "rcv_auth_msg_dhchap_reply_cmpl_wait4next", info);
3421 	emlxs_dhc_auth_complete(port, ndlp, 1);
3422 
3423 	return (node_dhc->state);
3424 
3425 } /* emlxs_rcv_auth_msg_dhchap_reply_cmpl_wait4next */
3426 
3427 
3428 
3429 /*
3430  * This routine should be set to emlxs_disc_neverdev as it shouldnot happen.
3431  *
3432  */
3433 /* ARGSUSED */
3434 static uint32_t
emlxs_cmpl_auth_msg_dhchap_reply_cmpl_wait4next(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)3435 emlxs_cmpl_auth_msg_dhchap_reply_cmpl_wait4next(
3436 emlxs_port_t *port,
3437 /* CHANNEL * rp, */ void *arg1,
3438 /* IOCBQ  * iocbq, */ void *arg2,
3439 /* MATCHMAP * mp, */ void *arg3,
3440 /* NODELIST * ndlp */ void *arg4,
3441 uint32_t evt)
3442 {
3443 	NODELIST *ndlp = (NODELIST *)arg4;
3444 
3445 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
3446 	    "cmpl_auth_msg_dhchap_reply_cmpl_wait4next. 0x%x.Not ipleted.",
3447 	    ndlp->nlp_DID);
3448 
3449 	return (0);
3450 
3451 } /* emlxs_cmpl_auth_msg_dhchap_reply_cmpl_wait4next */
3452 
3453 
3454 /*
3455  * emlxs_rcv_auth_msg_dhchap_success_issue_wait4next
3456  *
3457  * This routine is supported
3458  * for HBA in either auth initiator mode or responder mode.
3459  *
3460  * This routine is invoked when the host as the auth responder received
3461  * an unsolicited ELS AUTH msg from the NxPort as the auth
3462  * initiator that already received the ELS DHCHAP_Success.
3463  *
3464  * If the host is the auth initiator and since the AUTH transction is
3465  * already in progress, therefore, any auth els msg should not
3466  * happen and if happened, RJT and move to NPR_NODE.
3467  *
3468  * If the host is the auth reponder, this unsolicited els auth msg should
3469  * be DHCHAP_Success for this bi-directional auth
3470  * transaction. In which case, the host should send ACC back and move state
3471  * to REG_LOGIN. If this unsolicited els auth msg is
3472  * DHCHAP_Reject, which could mean that the auth failed, then host should
3473  * send back ACC and set the next state to NPR_NODE.
3474  *
3475  */
3476 /* ARGSUSED */
3477 static uint32_t
emlxs_rcv_auth_msg_dhchap_success_issue_wait4next(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)3478 emlxs_rcv_auth_msg_dhchap_success_issue_wait4next(
3479 emlxs_port_t *port,
3480 /* CHANNEL * rp, */ void *arg1,
3481 /* IOCBQ * iocbq, */ void *arg2,
3482 /* MATCHMAP * mp, */ void *arg3,
3483 /* NODELIST * ndlp */ void *arg4,
3484 uint32_t evt)
3485 {
3486 	NODELIST *ndlp = (NODELIST *) arg4;
3487 
3488 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
3489 	    "rcv_auth_msg_dhchap_success_issue_wait4next. 0x%x. Not iplted.",
3490 	    ndlp->nlp_DID);
3491 
3492 	return (0);
3493 
3494 } /* emlxs_rcv_auth_msg_dhchap_success_issue_wait4next */
3495 
3496 
3497 
3498 /*
3499  * ! emlxs_cmpl_auth_msg_dhchap_success_issue_wait4next
3500  *
3501  * This routine is invoked when
3502  * the host as the auth initiator received an solicited ACC/RJT from the
3503  * NxPort or FxPort that already received DHCHAP_Success
3504  * Msg the host sent before. in case of ACC, set next state = REG_LOGIN.
3505  * in case of RJT, set next state = NPR_NODE.
3506  *
3507  */
3508 /* ARGSUSED */
3509 static uint32_t
emlxs_cmpl_auth_msg_dhchap_success_issue_wait4next(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)3510 emlxs_cmpl_auth_msg_dhchap_success_issue_wait4next(
3511 emlxs_port_t *port,
3512 /* CHANNEL * rp, */ void *arg1,
3513 /* IOCBQ * iocbq, */ void *arg2,
3514 /* MATCHMAP * mp, */ void *arg3,
3515 /* NODELIST * ndlp */ void *arg4,
3516 uint32_t evt)
3517 {
3518 	NODELIST *ndlp = (NODELIST *)arg4;
3519 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
3520 
3521 	/*
3522 	 * Either host is the initiator and auth or (reauth bi-direct) is
3523 	 * done, so start host reauth heartbeat timer now if host side reauth
3524 	 * heart beat never get started. Or host is the responder and the
3525 	 * other entity is done with its reauth heart beat with
3526 	 * uni-directional auth. Anyway we start host side reauth heart beat
3527 	 * timer now.
3528 	 */
3529 
3530 	node_dhc->flag &= ~NLP_REMOTE_AUTH;
3531 	node_dhc->flag |= NLP_SET_REAUTH_TIME;
3532 
3533 	emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_SUCCESS, 0, 0);
3534 	emlxs_log_auth_event(port, ndlp,
3535 	    "cmpl_auth_msg_dhchap_success_issue_wait4next",
3536 	    "Host-initiated-bidir-auth-success");
3537 	emlxs_dhc_auth_complete(port, ndlp, 0);
3538 
3539 	return (node_dhc->state);
3540 
3541 } /* emlxs_cmpl_auth_msg_dhchap_success_issue_wait4next */
3542 
3543 
3544 /*
3545  * ! emlxs_cmpl_auth_msg_auth_negotiate_rcv
3546  *
3547  * This routine is invoked when
3548  * the host received the solicited ACC/RJT ELS cmd from an FxPort or an
3549  * NxPort that has received the ELS DHCHAP_Challenge.
3550  * The host is the auth responder and the auth transaction is still in
3551  * progress.
3552  *
3553  */
3554 /* ARGSUSED */
3555 static uint32_t
emlxs_cmpl_auth_msg_auth_negotiate_rcv(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)3556 emlxs_cmpl_auth_msg_auth_negotiate_rcv(
3557 emlxs_port_t *port,
3558 /* CHANNEL * rp, */ void *arg1,
3559 /* IOCBQ * iocbq, */ void *arg2,
3560 /* MATCHMAP * mp, */ void *arg3,
3561 /* NODELIST * ndlp */ void *arg4,
3562 uint32_t evt)
3563 {
3564 	NODELIST *ndlp = (NODELIST *)arg4;
3565 
3566 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
3567 	    "cmpl_auth_msg_auth_negotiate_rcv called. 0x%x. Not implemented.",
3568 	    ndlp->nlp_DID);
3569 
3570 	return (0);
3571 
3572 } /* emlxs_cmpl_auth_msg_auth_negotiate_rcv */
3573 
3574 
3575 
3576 /*
3577  * ! emlxs_rcv_auth_msg_dhchap_challenge_issue
3578  *
3579  * \pre \post \param   phba \param   ndlp \param   arg \param   evt \return
3580  * uint32_t \b Description: This routine should be
3581  * emlxs_disc_neverdev. The host is the auth responder and the auth
3582  * transaction is still in progress, any unsolicited els auth
3583  * msg is unexpected and should not happen in normal case.
3584  *
3585  * If DHCHAP_Reject, ACC and next state = NPR_NODE. anything else, RJT and
3586  * next state = NPR_NODE.
3587  */
3588 /* ARGSUSED */
3589 static uint32_t
emlxs_rcv_auth_msg_dhchap_challenge_issue(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)3590 emlxs_rcv_auth_msg_dhchap_challenge_issue(
3591 emlxs_port_t *port,
3592 /* CHANNEL * rp, */ void *arg1,
3593 /* IOCBQ * iocbq, */ void *arg2,
3594 /* MATCHMAP * mp, */ void *arg3,
3595 /* NODELIST * ndlp */ void *arg4,
3596 uint32_t evt)
3597 {
3598 	NODELIST *ndlp = (NODELIST *)arg4;
3599 
3600 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
3601 	    "rcv_auth_msg_dhchap_challenge_issue called. 0x%x. Not iplted.",
3602 	    ndlp->nlp_DID);
3603 
3604 	return (0);
3605 
3606 } /* emlxs_rcv_auth_msg_dhchap_challenge_issue */
3607 
3608 
3609 
3610 /*
3611  * ! emlxs_cmpl_auth_msg_dhchap_challenge_issue
3612  *
3613  * \pre \post \param   phba \param   ndlp \param   arg \param   evt \return
3614  * uint32_t \b Description: This routine is invoked when
3615  * the host as the responder received the solicited response (ACC or RJT)
3616  * from initiator to the DHCHAP_Challenge msg sent from
3617  * host. In case of ACC, the next state = DHCHAP_CHALLENGE_CMPL_WAIT4NEXT
3618  * In case of RJT, the next state = NPR_NODE.
3619  *
3620  */
3621 /* ARGSUSED */
3622 static uint32_t
emlxs_cmpl_auth_msg_dhchap_challenge_issue(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)3623 emlxs_cmpl_auth_msg_dhchap_challenge_issue(
3624 emlxs_port_t *port,
3625 /* CHANNEL * rp, */ void *arg1,
3626 /* IOCBQ * iocbq, */ void *arg2,
3627 /* MATCHMAP * mp, */ void *arg3,
3628 /* NODELIST * ndlp */ void *arg4,
3629 uint32_t evt)
3630 {
3631 	NODELIST *ndlp = (NODELIST *)arg4;
3632 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
3633 
3634 	/*
3635 	 * The next state should be
3636 	 * emlxs_rcv_auth_msg_dhchap_challenge_cmpl_wait4next
3637 	 */
3638 	emlxs_dhc_state(port, ndlp,
3639 	    NODE_STATE_DHCHAP_CHALLENGE_CMPL_WAIT4NEXT, 0, 0);
3640 
3641 	/* Start the fc_authrsp_timeout timer */
3642 	if (node_dhc->nlp_authrsp_tmo == 0) {
3643 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
3644 	    "cmpl_auth_msg_dhchap_challenge_issue: Starting authrsp timer.");
3645 
3646 		node_dhc->nlp_authrsp_tmo = DRV_TIME +
3647 		    node_dhc->auth_cfg.authentication_timeout;
3648 	}
3649 	return (node_dhc->state);
3650 
3651 } /* emlxs_cmpl_auth_msg_dhchap_challenge_issue */
3652 
3653 
3654 /*
3655  * ! emlxs_rcv_auth_msg_dhchap_challenge_cmpl_wait4next
3656  *
3657  * \pre \post \param   phba \param   ndlp \param   arg \param   evt \return
3658  * uint32_t \b Description: This routine is invoked when
3659  * the host as the auth responder received an unsolicited auth msg from the
3660  * FxPort or NxPort that already sent ACC to the DHCH_
3661  * Challenge it received. In normal case this unsolicited auth msg should
3662  * be DHCHAP_Reply msg from the initiator.
3663  *
3664  * For DHCHAP_Reply msg, the host send back ACC and then do verification
3665  * (hash?) and send back DHCHAP_Success and next state as
3666  * DHCHAP_SUCCESS_ISSUE or DHCHAP_Reject and next state as NPR_NODE based on
3667  * the verification result.
3668  *
3669  * For bi-directional auth transaction, Reply msg should have the new
3670  * challenge value from the initiator. thus the Success msg
3671  * sent out should have the corresponding Reply from the responder.
3672  *
3673  * For uni-directional, Reply msg received does not contains the new
3674  * challenge and therefore the Success msg does not include the
3675  * Reply msg.
3676  *
3677  * For DHCHAP_Reject, send ACC and moved to the next state NPR_NODE. For
3678  * anything else, send RJT and moved to NPR_NODE.
3679  *
3680  */
3681 /* ARGSUSED */
3682 static uint32_t
emlxs_rcv_auth_msg_dhchap_challenge_cmpl_wait4next(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)3683 emlxs_rcv_auth_msg_dhchap_challenge_cmpl_wait4next(
3684 emlxs_port_t *port,
3685 /* CHANNEL * rp, */ void *arg1,
3686 /* IOCBQ * iocbq, */ void *arg2,
3687 /* MATCHMAP * mp, */ void *arg3,
3688 /* NODELIST * ndlp */ void *arg4,
3689 uint32_t evt)
3690 {
3691 	emlxs_port_dhc_t *port_dhc = &port->port_dhc;
3692 	IOCBQ *iocbq = (IOCBQ *)arg2;
3693 	MATCHMAP *mp = (MATCHMAP *)arg3;
3694 	NODELIST *ndlp = (NODELIST *)arg4;
3695 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
3696 	uint8_t *bp;
3697 	uint32_t *lp;
3698 	DHCHAP_REPLY_HDR *dh_reply;
3699 	uint8_t *tmp;
3700 	uint32_t rsp_len;
3701 	uint8_t rsp[20];	/* should cover SHA-1 and MD5's rsp */
3702 	uint32_t dhval_len;
3703 	uint8_t dhval[512];
3704 	uint32_t cval_len;
3705 	uint8_t cval[20];
3706 	uint32_t tran_id;
3707 	uint32_t *hash_val = NULL;
3708 	uint8_t ReasonCode;
3709 	uint8_t ReasonCodeExplanation;
3710 	AUTH_RJT *rjt;
3711 
3712 	/* ACC the ELS DHCHAP_Reply msg first */
3713 
3714 	(void) emlxs_els_reply(port, iocbq, ELS_CMD_ACC, ELS_CMD_AUTH, 0, 0);
3715 
3716 	bp = mp->virt;
3717 	lp = (uint32_t *)bp;
3718 
3719 	/*
3720 	 * send back ELS AUTH_Reject or DHCHAP_Success msg based on the
3721 	 * verification result. i.e., hash computation etc.
3722 	 */
3723 	dh_reply = (DHCHAP_REPLY_HDR *)((uint8_t *)lp);
3724 	tmp = (uint8_t *)((uint8_t *)lp);
3725 
3726 	tran_id = dh_reply->tran_id;
3727 
3728 	if (LE_SWAP32(tran_id) != node_dhc->nlp_auth_tranid_ini) {
3729 
3730 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
3731 	    "rcv_auth_msg_dhchap_challenge_cmpl_wait4next:0x%x 0x%x 0x%x",
3732 	    ndlp->nlp_DID, tran_id, node_dhc->nlp_auth_tranid_ini);
3733 
3734 		ReasonCode = AUTHRJT_FAILURE;
3735 		ReasonCodeExplanation = AUTHEXP_BAD_PROTOCOL;
3736 		goto Reject;
3737 	}
3738 
3739 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
3740 	    "rcv_a_m_dhch_chll_cmpl_wait4next:0x%x 0x%x 0x%x 0x%x 0x%x",
3741 	    ndlp->nlp_DID, tran_id, node_dhc->nlp_auth_tranid_ini,
3742 	    node_dhc->nlp_auth_tranid_rsp, dh_reply->auth_msg_code);
3743 
3744 	/* cancel the nlp_authrsp_timeout timer and send out Auth_Reject */
3745 	if (node_dhc->nlp_authrsp_tmo) {
3746 		node_dhc->nlp_authrsp_tmo = 0;
3747 	}
3748 	if (dh_reply->auth_msg_code == AUTH_REJECT) {
3749 
3750 		rjt = (AUTH_RJT *)((uint8_t *)lp);
3751 		ReasonCode = rjt->ReasonCode;
3752 		ReasonCodeExplanation = rjt->ReasonCodeExplanation;
3753 
3754 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
3755 	    "rcv_a_msg_dhch_chall_cmpl_wait4next:RJT rcved:0x%x 0x%x",
3756 	    ReasonCode, ReasonCodeExplanation);
3757 
3758 		switch (ReasonCode) {
3759 		case AUTHRJT_LOGIC_ERR:
3760 			switch (ReasonCodeExplanation) {
3761 			case AUTHEXP_MECH_UNUSABLE:
3762 			case AUTHEXP_DHGROUP_UNUSABLE:
3763 			case AUTHEXP_HASHFUNC_UNUSABLE:
3764 				ReasonCode = AUTHRJT_LOGIC_ERR;
3765 				ReasonCodeExplanation = AUTHEXP_RESTART_AUTH;
3766 				break;
3767 
3768 			case AUTHEXP_RESTART_AUTH:
3769 				/*
3770 				 * Cancel the rsp timer if not cancelled yet.
3771 				 * and restart auth tran now.
3772 				 */
3773 				if (node_dhc->nlp_authrsp_tmo != 0) {
3774 					node_dhc->nlp_authrsp_tmo = 0;
3775 					node_dhc->nlp_authrsp_tmocnt = 0;
3776 				}
3777 				if (emlxs_dhc_auth_start(port, ndlp,
3778 				    NULL, NULL) != 0) {
3779 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_debug_msg,
3780 				    "Reauth timeout.Auth initfailed. 0x%x %x",
3781 				    ndlp->nlp_DID, node_dhc->state);
3782 				}
3783 				return (node_dhc->state);
3784 
3785 			default:
3786 				ReasonCode = AUTHRJT_FAILURE;
3787 				ReasonCodeExplanation = AUTHEXP_AUTH_FAILED;
3788 				break;
3789 			}
3790 			break;
3791 
3792 		case AUTHRJT_FAILURE:
3793 		default:
3794 			ReasonCode = AUTHRJT_FAILURE;
3795 			ReasonCodeExplanation = AUTHEXP_AUTH_FAILED;
3796 			break;
3797 		}
3798 
3799 		goto Reject;
3800 
3801 	}
3802 	if (dh_reply->auth_msg_code == DHCHAP_REPLY) {
3803 
3804 		/* We must send out DHCHAP_Success msg and wait for ACC */
3805 		/* _AND_ if bi-dir auth, we have to wait for next */
3806 
3807 		/*
3808 		 * Send back DHCHAP_Success or AUTH_Reject based on the
3809 		 * verification result
3810 		 */
3811 		tmp += sizeof (DHCHAP_REPLY_HDR);
3812 		rsp_len = LE_SWAP32(*(uint32_t *)tmp);
3813 		tmp += sizeof (uint32_t);
3814 
3815 		/* collect the response data */
3816 		bcopy((void *)tmp, (void *)rsp, rsp_len);
3817 
3818 		tmp += rsp_len;
3819 		dhval_len = LE_SWAP32(*(uint32_t *)tmp);
3820 
3821 		tmp += sizeof (uint32_t);
3822 
3823 
3824 
3825 		if (dhval_len != 0) {
3826 			/* collect the DH value */
3827 			bcopy((void *)tmp, (void *)dhval, dhval_len);
3828 			tmp += dhval_len;
3829 		}
3830 		/*
3831 		 * Check to see if there is any challenge for bi-dir auth in
3832 		 * the reply msg
3833 		 */
3834 		cval_len = LE_SWAP32(*(uint32_t *)tmp);
3835 		if (cval_len != 0) {
3836 			/* collect challenge value */
3837 			tmp += sizeof (uint32_t);
3838 			bcopy((void *)tmp, (void *)cval, cval_len);
3839 
3840 			if (ndlp->nlp_DID == FABRIC_DID) {
3841 				node_dhc->nlp_auth_bidir = 1;
3842 			} else {
3843 				node_dhc->nlp_auth_bidir = 1;
3844 			}
3845 		} else {
3846 			node_dhc->nlp_auth_bidir = 0;
3847 		}
3848 
3849 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
3850 	    "rcv_a_m_dhchap_challenge_cmpl_wait4next:Reply:%x %lx %x %x %x\n",
3851 	    ndlp->nlp_DID, *(uint32_t *)rsp, rsp_len, dhval_len, cval_len);
3852 
3853 		/* Verify the response based on the hash func, dhgp_id etc. */
3854 		/*
3855 		 * all the information needed are stored in
3856 		 * node_dhc->hrsp_xxx or ndlp->nlp_auth_misc.
3857 		 */
3858 		/*
3859 		 * Basically compare the rsp value with the computed hash
3860 		 * value
3861 		 */
3862 
3863 		/* allocate hash_val first as rsp_len bytes */
3864 		/*
3865 		 * we set bi-cval pointer as NULL because we are using
3866 		 * node_dhc->hrsp_cval[]
3867 		 */
3868 		hash_val = emlxs_hash_verification(port, port_dhc, ndlp,
3869 		    (tran_id), dhval, (dhval_len), 1, 0);
3870 
3871 		if (hash_val == NULL) {
3872 			ReasonCode = AUTHRJT_FAILURE;
3873 			ReasonCodeExplanation = AUTHEXP_AUTH_FAILED;
3874 			goto Reject;
3875 		}
3876 		if (bcmp((void *) rsp, (void *)hash_val, rsp_len)) {
3877 			/* not identical */
3878 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
3879 	    "rcv_auth_msg_dhchap_challenge_cmpl_wait4next: Not authted(1).");
3880 
3881 			ReasonCode = AUTHRJT_FAILURE;
3882 			ReasonCodeExplanation = AUTHEXP_AUTH_FAILED;
3883 			goto Reject;
3884 		}
3885 		kmem_free(hash_val, rsp_len);
3886 		hash_val = NULL;
3887 
3888 		/* generate the reply based on the challenge received if any */
3889 		if ((cval_len) != 0) {
3890 			/*
3891 			 * Cal R2 = H (Ti || Km || Ca2) Ca2 = H (C2 || ((g^y
3892 			 * mod p)^x mod p) ) = H (C2 || (g^(x*y) mod p)) = H
3893 			 * (C2 || seskey) Km is the password associated with
3894 			 * responder. Here cval: C2 dhval: (g^y mod p)
3895 			 */
3896 			hash_val = emlxs_hash_get_R2(port, port_dhc,
3897 			    ndlp, (tran_id), dhval,
3898 			    (dhval_len), 1, cval);
3899 
3900 			if (hash_val == NULL) {
3901 				ReasonCode = AUTHRJT_FAILURE;
3902 				ReasonCodeExplanation = AUTHEXP_AUTH_FAILED;
3903 				goto Reject;
3904 			}
3905 		}
3906 		emlxs_dhc_state(port, ndlp,
3907 		    NODE_STATE_DHCHAP_SUCCESS_ISSUE, 0, 0);
3908 
3909 		if (emlxs_issue_dhchap_success(port, ndlp, 0,
3910 		    (uint8_t *)hash_val)) {
3911 			ReasonCode = AUTHRJT_FAILURE;
3912 			ReasonCodeExplanation = AUTHEXP_AUTH_FAILED;
3913 			goto Reject;
3914 		}
3915 	}
3916 	return (node_dhc->state);
3917 
3918 Reject:
3919 
3920 	emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_FAILED,
3921 	    ReasonCode, ReasonCodeExplanation);
3922 	(void) emlxs_issue_auth_reject(port, ndlp, 0, 0, ReasonCode,
3923 	    ReasonCodeExplanation);
3924 	emlxs_dhc_auth_complete(port, ndlp, 1);
3925 
3926 	return (node_dhc->state);
3927 
3928 } /* emlxs_rcv_auth_msg_dhchap_challenge_cmpl_wait4next */
3929 
3930 
3931 
3932 /*
3933  * This routine should be emlxs_disc_neverdev.
3934  *
3935  */
3936 /* ARGSUSED */
3937 static uint32_t
emlxs_cmpl_auth_msg_dhchap_challenge_cmpl_wait4next(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)3938 emlxs_cmpl_auth_msg_dhchap_challenge_cmpl_wait4next(
3939 emlxs_port_t *port,
3940 /* CHANNEL * rp, */ void *arg1,
3941 /* IOCBQ * iocbq, */ void *arg2,
3942 /* MATCHMAP * mp, */ void *arg3,
3943 /* NODELIST * ndlp */ void *arg4,
3944 uint32_t evt)
3945 {
3946 	NODELIST *ndlp = (NODELIST *)arg4;
3947 
3948 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
3949 	    "cmpl_a_m_dhch_chall_cmpl_wait4next.0x%x. Not implemented.",
3950 	    ndlp->nlp_DID);
3951 
3952 	return (0);
3953 
3954 } /* emlxs_cmpl_auth_msg_dhchap_challenge_cmpl_wait4next */
3955 
3956 
3957 /*
3958  * ! emlxs_rcv_auth_msg_dhchap_success_issue
3959  *
3960  * \pre \post \param   phba \param   ndlp \param   arg \param   evt \return
3961  * uint32_t \b Description:
3962  *
3963  * The host is the auth responder and the auth transaction is still in
3964  * progress, any unsolicited els auth msg is unexpected and
3965  * should not happen. If DHCHAP_Reject received, ACC back and move to next
3966  * state NPR_NODE. anything else, RJT and move to
3967  * NPR_NODE.
3968  */
3969 /* ARGSUSED */
3970 static uint32_t
emlxs_rcv_auth_msg_dhchap_success_issue(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)3971 emlxs_rcv_auth_msg_dhchap_success_issue(
3972 emlxs_port_t *port,
3973 /* CHANNEL * rp, */ void *arg1,
3974 /* IOCBQ * iocbq, */ void *arg2,
3975 /* MATCHMAP * mp, */ void *arg3,
3976 /* NODELIST * ndlp */ void *arg4,
3977 uint32_t evt)
3978 {
3979 	NODELIST *ndlp = (NODELIST *)arg4;
3980 
3981 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
3982 	    "rcv_a_m_dhch_success_issue called. did=0x%x. Not implemented.",
3983 	    ndlp->nlp_DID);
3984 
3985 	return (0);
3986 
3987 } /* emlxs_rcv_auth_msg_dhchap_success_issue */
3988 
3989 
3990 
3991 /*
3992  * emlxs_cmpl_auth_msg_dhchap_success_issue
3993  *
3994  * This routine is invoked when
3995  * host as the auth responder received the solicited response (ACC or RJT)
3996  * from the initiator that received DHCHAP_ Success.
3997  *
3998  * For uni-dirctional authentication, we are done so the next state =
3999  * REG_LOGIN for bi-directional authentication, we will expect
4000  * DHCHAP_Success msg. so the next state = DHCHAP_SUCCESS_CMPL_WAIT4NEXT
4001  * and start the emlxs_dhc_authrsp_timeout timer
4002  */
4003 /* ARGSUSED */
4004 static uint32_t
emlxs_cmpl_auth_msg_dhchap_success_issue(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)4005 emlxs_cmpl_auth_msg_dhchap_success_issue(
4006 emlxs_port_t *port,
4007 /* CHANNEL * rp, */ void *arg1,
4008 /* IOCBQ * iocbq, */ void *arg2,
4009 /* MATCHMAP * mp, */ void *arg3,
4010 /* NODELIST * ndlp */ void *arg4,
4011 uint32_t evt)
4012 {
4013 	NODELIST *ndlp = (NODELIST *)arg4;
4014 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
4015 
4016 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4017 	    "cmpl_a_m_dhch_success_issue: did=0x%x auth_bidir=0x%x",
4018 	    ndlp->nlp_DID, node_dhc->nlp_auth_bidir);
4019 
4020 	if (node_dhc->nlp_auth_bidir == 1) {
4021 		/* we would expect the bi-dir authentication result */
4022 
4023 		/*
4024 		 * the next state should be
4025 		 * emlxs_rcv_auth_msg_dhchap_success_cmpl_wait4next
4026 		 */
4027 		emlxs_dhc_state(port, ndlp,
4028 		    NODE_STATE_DHCHAP_SUCCESS_CMPL_WAIT4NEXT, 0, 0);
4029 
4030 		/* start the emlxs_dhc_authrsp_timeout timer */
4031 		node_dhc->nlp_authrsp_tmo = DRV_TIME +
4032 		    node_dhc->auth_cfg.authentication_timeout;
4033 	} else {
4034 		node_dhc->flag &= ~NLP_REMOTE_AUTH;
4035 
4036 		emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_SUCCESS, 0, 0);
4037 		emlxs_log_auth_event(port, ndlp,
4038 		    "cmpl_auth_msg_dhchap_success_issue",
4039 		    "Node-initiated-unidir-reauth-success");
4040 		emlxs_dhc_auth_complete(port, ndlp, 0);
4041 	}
4042 
4043 	return (node_dhc->state);
4044 
4045 } /* emlxs_cmpl_auth_msg_dhchap_success_issue */
4046 
4047 
4048 /* ARGSUSED */
4049 static uint32_t
emlxs_device_recov_unmapped_node(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)4050 emlxs_device_recov_unmapped_node(
4051 	emlxs_port_t *port,
4052 	void *arg1,
4053 	void *arg2,
4054 	void *arg3,
4055 	void *arg4,
4056 	uint32_t evt)
4057 {
4058 	NODELIST *ndlp = (NODELIST *)arg4;
4059 
4060 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4061 	    "device_recov_unmapped_node called. 0x%x. Not implemented.",
4062 	    ndlp->nlp_DID);
4063 
4064 	return (0);
4065 
4066 } /* emlxs_device_recov_unmapped_node */
4067 
4068 
4069 
4070 /* ARGSUSED */
4071 static uint32_t
emlxs_device_rm_npr_node(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)4072 emlxs_device_rm_npr_node(
4073 	emlxs_port_t *port,
4074 	void *arg1,
4075 	void *arg2,
4076 	void *arg3,
4077 	void *arg4,
4078 	uint32_t evt)
4079 {
4080 	NODELIST *ndlp = (NODELIST *)arg4;
4081 
4082 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4083 	    "device_rm_npr_node called. 0x%x. Not implemented.",
4084 	    ndlp->nlp_DID);
4085 
4086 	return (0);
4087 
4088 } /* emlxs_device_rm_npr_node */
4089 
4090 
4091 /* ARGSUSED */
4092 static uint32_t
emlxs_device_recov_npr_node(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)4093 emlxs_device_recov_npr_node(
4094 	emlxs_port_t *port,
4095 	void *arg1,
4096 	void *arg2,
4097 	void *arg3,
4098 	void *arg4,
4099 	uint32_t evt)
4100 {
4101 	NODELIST *ndlp = (NODELIST *)arg4;
4102 
4103 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4104 	    "device_recov_npr_node called. 0x%x. Not implemented.",
4105 	    ndlp->nlp_DID);
4106 
4107 	return (0);
4108 
4109 } /* emlxs_device_recov_npr_node */
4110 
4111 
4112 /* ARGSUSED */
4113 static uint32_t
emlxs_device_rem_auth(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)4114 emlxs_device_rem_auth(
4115 emlxs_port_t *port,
4116 /* CHANNEL * rp, */ void *arg1,
4117 /* IOCBQ * iocbq, */ void *arg2,
4118 /* MATCHMAP * mp, */ void *arg3,
4119 /* NODELIST * ndlp */ void *arg4,
4120 uint32_t evt)
4121 {
4122 	NODELIST *ndlp = (NODELIST *)arg4;
4123 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
4124 
4125 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4126 	    "device_rem_auth: 0x%x.",
4127 	    ndlp->nlp_DID);
4128 
4129 	emlxs_dhc_state(port, ndlp, NODE_STATE_UNKNOWN, 0, 0);
4130 
4131 	return (node_dhc->state);
4132 
4133 } /* emlxs_device_rem_auth */
4134 
4135 
4136 /*
4137  * This routine is invoked when linkdown event happens during authentication
4138  */
4139 /* ARGSUSED */
4140 static uint32_t
emlxs_device_recov_auth(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)4141 emlxs_device_recov_auth(
4142 emlxs_port_t *port,
4143 /* CHANNEL * rp, */ void *arg1,
4144 /* IOCBQ * iocbq, */ void *arg2,
4145 /* MATCHMAP * mp, */ void *arg3,
4146 /* NODELIST * ndlp */ void *arg4,
4147 uint32_t evt)
4148 {
4149 	NODELIST *ndlp = (NODELIST *)arg4;
4150 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
4151 
4152 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4153 	    "device_recov_auth: 0x%x.",
4154 	    ndlp->nlp_DID);
4155 
4156 	node_dhc->nlp_authrsp_tmo = 0;
4157 
4158 	emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_FAILED, 0, 0);
4159 
4160 	return (node_dhc->state);
4161 
4162 } /* emlxs_device_recov_auth */
4163 
4164 
4165 
4166 /*
4167  * This routine is invoked when the host as the responder sent out the
4168  * ELS DHCHAP_Success to the initiator, the initiator ACC
4169  * it. AND then the host received an unsolicited auth msg from the initiator,
4170  * this msg is supposed to be the ELS DHCHAP_Success
4171  * msg for the bi-directional authentication.
4172  *
4173  * next state should be REG_LOGIN
4174  */
4175 /* ARGSUSED */
4176 static uint32_t
emlxs_rcv_auth_msg_dhchap_success_cmpl_wait4next(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)4177 emlxs_rcv_auth_msg_dhchap_success_cmpl_wait4next(
4178 emlxs_port_t *port,
4179 /* CHANNEL * rp, */ void *arg1,
4180 /* IOCBQ * iocbq, */ void *arg2,
4181 /* MATCHMAP * mp, */ void *arg3,
4182 /* NODELIST * ndlp */ void *arg4,
4183 uint32_t evt)
4184 {
4185 	IOCBQ *iocbq = (IOCBQ *)arg2;
4186 	MATCHMAP *mp = (MATCHMAP *)arg3;
4187 	NODELIST *ndlp = (NODELIST *)arg4;
4188 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
4189 	uint8_t *bp;
4190 	uint32_t *lp;
4191 	DHCHAP_SUCCESS_HDR *dh_success;
4192 	AUTH_RJT *auth_rjt;
4193 	uint8_t ReasonCode;
4194 	uint8_t ReasonCodeExplanation;
4195 
4196 	bp = mp->virt;
4197 	lp = (uint32_t *)bp;
4198 
4199 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4200 	    "rcv_auth_msg_dhchap_success_cmpl_wait4next: did=0x%x",
4201 	    ndlp->nlp_DID);
4202 
4203 	dh_success = (DHCHAP_SUCCESS_HDR *)((uint8_t *)lp);
4204 
4205 	(void) emlxs_els_reply(port, iocbq, ELS_CMD_ACC, ELS_CMD_AUTH, 0, 0);
4206 
4207 	if (dh_success->auth_msg_code == AUTH_REJECT) {
4208 		/* ACC it and retry etc.  */
4209 		auth_rjt = (AUTH_RJT *)dh_success;
4210 		ReasonCode = auth_rjt->ReasonCode;
4211 		ReasonCodeExplanation = auth_rjt->ReasonCodeExplanation;
4212 
4213 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4214 	    "rcv_a_m_dhch_success_cmpl_wait4next:REJECT rvd. 0x%x 0x%x 0x%x",
4215 	    ndlp->nlp_DID, ReasonCode, ReasonCodeExplanation);
4216 
4217 		switch (ReasonCode) {
4218 		case AUTHRJT_LOGIC_ERR:
4219 			switch (ReasonCodeExplanation) {
4220 			case AUTHEXP_MECH_UNUSABLE:
4221 			case AUTHEXP_DHGROUP_UNUSABLE:
4222 			case AUTHEXP_HASHFUNC_UNUSABLE:
4223 				ReasonCode = AUTHRJT_LOGIC_ERR;
4224 				ReasonCodeExplanation = AUTHEXP_RESTART_AUTH;
4225 				break;
4226 
4227 			case AUTHEXP_RESTART_AUTH:
4228 				/*
4229 				 * Cancel the rsp timer if not cancelled yet.
4230 				 * and restart auth tran now.
4231 				 */
4232 				if (node_dhc->nlp_authrsp_tmo != 0) {
4233 					node_dhc->nlp_authrsp_tmo = 0;
4234 					node_dhc->nlp_authrsp_tmocnt = 0;
4235 				}
4236 				if (emlxs_dhc_auth_start(port, ndlp,
4237 				    NULL, NULL) != 0) {
4238 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_debug_msg,
4239 				    "Reauth timeout. Auth initfailed. 0x%x %x",
4240 				    ndlp->nlp_DID, node_dhc->state);
4241 				}
4242 				return (node_dhc->state);
4243 
4244 			default:
4245 				ReasonCode = AUTHRJT_FAILURE;
4246 				ReasonCodeExplanation = AUTHEXP_AUTH_FAILED;
4247 				break;
4248 
4249 			}
4250 			break;
4251 
4252 		case AUTHRJT_FAILURE:
4253 		default:
4254 			ReasonCode = AUTHRJT_FAILURE;
4255 			ReasonCodeExplanation = AUTHEXP_AUTH_FAILED;
4256 			break;
4257 
4258 		}
4259 
4260 		goto Reject;
4261 
4262 	} else if (dh_success->auth_msg_code == DHCHAP_SUCCESS) {
4263 		if (LE_SWAP32(dh_success->tran_id) !=
4264 		    node_dhc->nlp_auth_tranid_ini) {
4265 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4266 	    "rcv_a_m_dhch_success_cmpl_wait4next: 0x%x 0x%lx, 0x%lx",
4267 	    ndlp->nlp_DID, dh_success->tran_id, node_dhc->nlp_auth_tranid_ini);
4268 
4269 			ReasonCode = AUTHRJT_FAILURE;
4270 			ReasonCodeExplanation = AUTHEXP_BAD_PROTOCOL;
4271 			goto Reject;
4272 		}
4273 		node_dhc->flag |= NLP_REMOTE_AUTH;
4274 
4275 		emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_SUCCESS, 0, 0);
4276 		emlxs_log_auth_event(port, ndlp,
4277 		    "rcv_auth_msg_dhchap_success_cmpl_wait4next",
4278 		    "Node-initiated-bidir-reauth-success");
4279 		emlxs_dhc_auth_complete(port, ndlp, 0);
4280 	} else {
4281 		ReasonCode = AUTHRJT_FAILURE;
4282 		ReasonCodeExplanation = AUTHEXP_BAD_PROTOCOL;
4283 		goto Reject;
4284 	}
4285 
4286 	return (node_dhc->state);
4287 
4288 Reject:
4289 
4290 	emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_FAILED,
4291 	    ReasonCode, ReasonCodeExplanation);
4292 	(void) emlxs_issue_auth_reject(port, ndlp, 0, 0, ReasonCode,
4293 	    ReasonCodeExplanation);
4294 	emlxs_dhc_auth_complete(port, ndlp, 1);
4295 
4296 	return (node_dhc->state);
4297 
4298 } /* emlxs_rcv_auth_msg_dhchap_success_cmpl_wait4next */
4299 
4300 
4301 /* ARGSUSED */
4302 static uint32_t
emlxs_cmpl_auth_msg_dhchap_success_cmpl_wait4next(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)4303 emlxs_cmpl_auth_msg_dhchap_success_cmpl_wait4next(
4304 emlxs_port_t *port,
4305 /* CHANNEL * rp, */ void *arg1,
4306 /* IOCBQ * iocbq, */ void *arg2,
4307 /* MATCHMAP * mp, */ void *arg3,
4308 /* NODELIST * ndlp */ void *arg4,
4309 uint32_t evt)
4310 {
4311 
4312 	return (0);
4313 
4314 } /* emlxs_cmpl_auth_msg_dhchap_success_cmpl_wait4next */
4315 
4316 
4317 /* ARGSUSED */
4318 static uint32_t
emlxs_rcv_auth_msg_auth_negotiate_rcv(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)4319 emlxs_rcv_auth_msg_auth_negotiate_rcv(
4320 emlxs_port_t *port,
4321 /* CHANNEL * rp, */ void *arg1,
4322 /* IOCBQ * iocbq, */ void *arg2,
4323 /* MATCHMAP * mp, */ void *arg3,
4324 /* NODELIST * ndlp */ void *arg4,
4325 uint32_t evt)
4326 {
4327 	NODELIST *ndlp = (NODELIST *)arg4;
4328 
4329 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4330 	    "rcv_a_m_auth_negotiate_rcv called. did=0x%x. Not implemented.",
4331 	    ndlp->nlp_DID);
4332 
4333 	return (0);
4334 
4335 } /* emlxs_rcv_auth_msg_auth_negotiate_rcv */
4336 
4337 
4338 /* ARGSUSED */
4339 static uint32_t
emlxs_rcv_auth_msg_npr_node(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)4340 emlxs_rcv_auth_msg_npr_node(
4341 emlxs_port_t *port,
4342 /* CHANNEL  * rp, */ void *arg1,
4343 /* IOCBQ * iocbq, */ void *arg2,
4344 /* MATCHMAP * mp, */ void *arg3,
4345 /* NODELIST * ndlp */ void *arg4,
4346 	uint32_t evt)
4347 {
4348 	IOCBQ *iocbq = (IOCBQ *)arg2;
4349 	MATCHMAP *mp = (MATCHMAP *)arg3;
4350 	NODELIST *ndlp = (NODELIST *)arg4;
4351 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
4352 	uint8_t *bp;
4353 
4354 	uint32_t *lp;
4355 	uint32_t msglen;
4356 	uint8_t *tmp;
4357 
4358 	AUTH_MSG_HDR *msg;
4359 
4360 	uint8_t *temp;
4361 	uint32_t rc, i, hs_id[2], dh_id[5];
4362 					/* from initiator */
4363 	uint32_t hash_id, dhgp_id;	/* to be used by responder */
4364 	uint16_t num_hs = 0;
4365 	uint16_t num_dh = 0;
4366 
4367 	bp = mp->virt;
4368 	lp = (uint32_t *)bp;
4369 
4370 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4371 	    "rcv_auth_msg_npr_node:");
4372 
4373 	/*
4374 	 * 1. process the auth msg, should acc first no matter what. 2.
4375 	 * return DHCHAP_Challenge for AUTH_Negotiate auth msg, AUTH_Reject
4376 	 * for anything else.
4377 	 */
4378 	(void) emlxs_els_reply(port, iocbq, ELS_CMD_ACC, ELS_CMD_AUTH, 0, 0);
4379 
4380 	msg = (AUTH_MSG_HDR *)((uint8_t *)lp);
4381 	msglen = msg->msg_len;
4382 	tmp = ((uint8_t *)lp);
4383 
4384 	/* temp is used for error checking */
4385 	temp = (uint8_t *)((uint8_t *)lp);
4386 	/* Check the auth_els_code */
4387 	if (((*(uint32_t *)temp) & 0xFFFFFFFF) != LE_SWAP32(0x90000B01)) {
4388 		/* ReasonCode = AUTHRJT_FAILURE; */
4389 		/* ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD; */
4390 
4391 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4392 		    "rcv_auth_msg_npr_node: payload(1)=0x%x",
4393 		    (*(uint32_t *)temp));
4394 
4395 		goto AUTH_Reject;
4396 	}
4397 	temp += 3 * sizeof (uint32_t);
4398 	/* Check name tag and name length */
4399 	if (((*(uint32_t *)temp) & 0xFFFFFFFF) != LE_SWAP32(0x00010008)) {
4400 		/* ReasonCode = AUTHRJT_FAILURE; */
4401 		/* ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD; */
4402 
4403 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4404 		    "rcv_auth_msg_npr_node: payload(2)=0x%x",
4405 		    (*(uint32_t *)temp));
4406 
4407 		goto AUTH_Reject;
4408 	}
4409 	temp += sizeof (uint32_t) + 8;
4410 	/* Check proto_num */
4411 	if (((*(uint32_t *)temp) & 0xFFFFFFFF) != LE_SWAP32(0x00000001)) {
4412 		/* ReasonCode = AUTHRJT_FAILURE; */
4413 		/* ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD; */
4414 
4415 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4416 		    "rcv_auth_msg_npr_node: payload(3)=0x%x",
4417 		    (*(uint32_t *)temp));
4418 
4419 		goto AUTH_Reject;
4420 	}
4421 	temp += sizeof (uint32_t);
4422 	/* Get para_len */
4423 	/* para_len = LE_SWAP32(*(uint32_t *)temp); */
4424 
4425 	temp += sizeof (uint32_t);
4426 	/* Check proto_id */
4427 	if (((*(uint32_t *)temp) & 0xFFFFFFFF) != AUTH_DHCHAP) {
4428 		/* ReasonCode = AUTHRJT_FAILURE; */
4429 		/* ReasonCodeExplanation = AUTHEXP_BAD_PROTOCOL; */
4430 
4431 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4432 		    "rcv_auth_msg_npr_node: payload(4)=0x%x",
4433 		    (*(uint32_t *)temp));
4434 
4435 		goto AUTH_Reject;
4436 	}
4437 	temp += sizeof (uint32_t);
4438 	/* Check hashlist tag */
4439 	if ((LE_SWAP32(*(uint32_t *)temp) & 0xFFFF0000) >> 16 !=
4440 	    LE_SWAP16(HASH_LIST_TAG)) {
4441 		/* ReasonCode = AUTHRJT_FAILURE; */
4442 		/* ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD; */
4443 
4444 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4445 		    "rcv_auth_msg_npr_node: payload(5)=0x%x",
4446 		    (LE_SWAP32(*(uint32_t *)temp) & 0xFFFF0000) >> 16);
4447 
4448 		goto AUTH_Reject;
4449 	}
4450 	/* Get num_hs  */
4451 	num_hs = LE_SWAP32(*(uint32_t *)temp) & 0x0000FFFF;
4452 
4453 	temp += sizeof (uint32_t);
4454 	/* Check HashList_value1 */
4455 	hs_id[0] = *(uint32_t *)temp;
4456 
4457 	if ((hs_id[0] != AUTH_MD5) && (hs_id[0] != AUTH_SHA1)) {
4458 		/* ReasonCode = AUTHRJT_LOGIC_ERR; */
4459 		/* ReasonCodeExplanation = AUTHEXP_HASHFUNC_UNUSABLE; */
4460 
4461 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4462 		    "rcv_auth_msg_npr_node: payload(6)=0x%x",
4463 		    (*(uint32_t *)temp));
4464 
4465 		goto AUTH_Reject;
4466 	}
4467 	if (num_hs == 1) {
4468 		hs_id[1] = 0;
4469 	} else if (num_hs == 2) {
4470 		temp += sizeof (uint32_t);
4471 		hs_id[1] = *(uint32_t *)temp;
4472 
4473 		if ((hs_id[1] != AUTH_MD5) && (hs_id[1] != AUTH_SHA1)) {
4474 			/* ReasonCode = AUTHRJT_LOGIC_ERR; */
4475 			/* ReasonCodeExplanation = AUTHEXP_HASHFUNC_UNUSABLE; */
4476 
4477 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4478 			    "rcv_auth_msg_npr_node: payload(7)=0x%x",
4479 			    (*(uint32_t *)temp));
4480 
4481 			goto AUTH_Reject;
4482 		}
4483 		if (hs_id[0] == hs_id[1]) {
4484 			/* ReasonCode = AUTHRJT_FAILURE; */
4485 			/* ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD; */
4486 
4487 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4488 			    "rcv_auth_msg_npr_node: payload(8)=0x%x",
4489 			    (*(uint32_t *)temp));
4490 
4491 			goto AUTH_Reject;
4492 		}
4493 	} else {
4494 		/* ReasonCode = AUTHRJT_FAILURE; */
4495 		/* ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD; */
4496 
4497 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4498 		    "rcv_auth_msg_npr_node: payload(9)=0x%x",
4499 		    (*(uint32_t *)(temp - sizeof (uint32_t))));
4500 
4501 		goto AUTH_Reject;
4502 	}
4503 
4504 	/* Which hash_id should we use */
4505 	if (num_hs == 1) {
4506 		/*
4507 		 * We always use the highest priority specified by us if we
4508 		 * match initiator's , Otherwise, we use the next higher we
4509 		 * both have. CR 26238
4510 		 */
4511 		if (node_dhc->auth_cfg.hash_priority[0] == hs_id[0]) {
4512 			hash_id = node_dhc->auth_cfg.hash_priority[0];
4513 		} else if (node_dhc->auth_cfg.hash_priority[1] == hs_id[0]) {
4514 			hash_id = node_dhc->auth_cfg.hash_priority[1];
4515 		} else {
4516 			/* ReasonCode = AUTHRJT_LOGIC_ERR; */
4517 			/* ReasonCodeExplanation = AUTHEXP_HASHFUNC_UNUSABLE; */
4518 
4519 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4520 			    "rcv_auth_msg_npr_node: payload(10)=0x%lx",
4521 			    (*(uint32_t *)temp));
4522 
4523 			goto AUTH_Reject;
4524 		}
4525 	} else {
4526 		/*
4527 		 * Since the initiator specified two hashs, we always select
4528 		 * our first one.
4529 		 */
4530 		hash_id = node_dhc->auth_cfg.hash_priority[0];
4531 	}
4532 
4533 	temp += sizeof (uint32_t);
4534 	/* Check DHgIDList_tag */
4535 	if ((LE_SWAP32(*(uint32_t *)temp) & 0xFFFF0000) >> 16 !=
4536 	    LE_SWAP16(DHGID_LIST_TAG)) {
4537 		/* ReasonCode = AUTHRJT_FAILURE; */
4538 		/* ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD; */
4539 
4540 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4541 		    "rcv_auth_msg_npr_node: payload(11)=0x%lx",
4542 		    (*(uint32_t *)temp));
4543 
4544 		goto AUTH_Reject;
4545 	}
4546 	/* Get num_dh */
4547 	num_dh = LE_SWAP32(*(uint32_t *)temp) & 0x0000FFFF;
4548 
4549 	if (num_dh == 0) {
4550 		/* ReasonCode = AUTHRJT_FAILURE; */
4551 		/* ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD; */
4552 
4553 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4554 		    "rcv_auth_msg_npr_node: payload(12)=0x%lx",
4555 		    (*(uint32_t *)temp));
4556 
4557 		goto AUTH_Reject;
4558 	}
4559 	for (i = 0; i < num_dh; i++) {
4560 		temp += sizeof (uint32_t);
4561 		/* Check DHgIDList_g0 */
4562 		dh_id[i] = (*(uint32_t *)temp);
4563 	}
4564 
4565 	rc = emlxs_check_dhgp(port, ndlp, dh_id, num_dh, &dhgp_id);
4566 
4567 	if (rc == 1) {
4568 		/* ReasonCode = AUTHRJT_LOGIC_ERR; */
4569 		/* ReasonCodeExplanation = AUTHEXP_DHGROUP_UNUSABLE; */
4570 
4571 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4572 		    "rcv_auth_msg_npr_node: payload(13)=0x%lx",
4573 		    (*(uint32_t *)temp));
4574 
4575 		goto AUTH_Reject;
4576 	} else if (rc == 2) {
4577 		/* ReasonCode = AUTHRJT_FAILURE; */
4578 		/* ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD; */
4579 
4580 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4581 		    "rcv_auth_msg_npr_node: payload(14)=0x%lx",
4582 		    (*(uint32_t *)temp));
4583 
4584 		goto AUTH_Reject;
4585 	}
4586 	/* We should update the tran_id */
4587 	node_dhc->nlp_auth_tranid_ini = msg->tran_id;
4588 
4589 	if (msg->auth_msg_code == AUTH_NEGOTIATE) {
4590 		node_dhc->nlp_auth_flag = 1;	/* ndlp is the initiator */
4591 
4592 		/* Send back the DHCHAP_Challenge with the proper paramaters */
4593 		if (emlxs_issue_dhchap_challenge(port, ndlp, 0, tmp,
4594 		    LE_SWAP32(msglen),
4595 		    hash_id, dhgp_id)) {
4596 			goto AUTH_Reject;
4597 		}
4598 		emlxs_dhc_state(port, ndlp,
4599 		    NODE_STATE_DHCHAP_CHALLENGE_ISSUE, 0, 0);
4600 
4601 	} else {
4602 		goto AUTH_Reject;
4603 	}
4604 
4605 	return (node_dhc->state);
4606 
4607 AUTH_Reject:
4608 
4609 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4610 	    "rcv_auth_msg_npr_node: AUTH_Reject it.");
4611 
4612 	return (node_dhc->state);
4613 
4614 } /* emlxs_rcv_auth_msg_npr_node */
4615 
4616 
4617 /* ARGSUSED */
4618 static uint32_t
emlxs_cmpl_auth_msg_npr_node(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)4619 emlxs_cmpl_auth_msg_npr_node(
4620 emlxs_port_t *port,
4621 /* CHANNEL * rp, */ void *arg1,
4622 /* IOCBQ * iocbq, */ void *arg2,
4623 /* MATCHMAP * mp, */ void *arg3,
4624 /* NODELIST * ndlp */ void *arg4,
4625 uint32_t evt)
4626 {
4627 	NODELIST *ndlp = (NODELIST *)arg4;
4628 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
4629 
4630 	/*
4631 	 * we donot cancel the nodev timeout here because we donot know if we
4632 	 * can get the authentication restarted from other side once we got
4633 	 * the new auth transaction kicked off we cancel nodev tmo
4634 	 * immediately.
4635 	 */
4636 	/* we goto change the hba state back to where it used to be */
4637 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4638 	    "cmpl_auth_msg_npr_node: 0x%x 0x%x prev_state=0x%x\n",
4639 	    ndlp->nlp_DID, node_dhc->state, node_dhc->prev_state);
4640 
4641 	return (node_dhc->state);
4642 
4643 } /* emlxs_cmpl_auth_msg_npr_node */
4644 
4645 
4646 /*
4647  * ! emlxs_rcv_auth_msg_unmapped_node
4648  *
4649  * \pre \post \param   phba \param   ndlp \param   arg \param   evt \return
4650  * uint32_t
4651  *
4652  * \b Description: This routine is invoked when the host received an
4653  * unsolicited els authentication msg from the Fx_Port which is
4654  * wellknown port 0xFFFFFE in unmapped state, or from Nx_Port which is
4655  * in the unmapped state meaning that it is either a target
4656  * which there is no scsi id associated with it or it could be another
4657  * initiator. (end-to-end)
4658  *
4659  * For the Fabric F_Port (FFFFFE) we mark the port to the state in re_auth
4660  * state without disruppting the traffic. Then the fabric
4661  * will go through the authentication processes until it is done.
4662  *
4663  * most of the cases, the fabric should send us AUTH_Negotiate ELS msg. Once
4664  * host received this auth_negotiate els msg, host
4665  * should sent back ACC first and then send random challenge, plus DH value
4666  * (i.e., host's publick key)
4667  *
4668  * Host side needs to store the challenge value and public key for later
4669  * verification usage. (i.e., to verify the response from
4670  * initiator)
4671  *
4672  * If two FC_Ports start the reauthentication transaction at the same time,
4673  * one of the two authentication transactions shall be
4674  * aborted. In case of Host and Fabric the Nx_Port shall remain the
4675  * authentication initiator, while the Fx_Port shall become
4676  * the authentication responder.
4677  *
4678  */
4679 /* ARGSUSED */
4680 static uint32_t
emlxs_rcv_auth_msg_unmapped_node(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)4681 emlxs_rcv_auth_msg_unmapped_node(
4682 emlxs_port_t *port,
4683 /* CHANNEL * rp, */ void *arg1,
4684 /* IOCBQ * iocbq, */ void *arg2,
4685 /* MATCHMAP * mp, */ void *arg3,
4686 /* NODELIST * ndlp */ void *arg4,
4687 	uint32_t evt)
4688 {
4689 	IOCBQ *iocbq = (IOCBQ *)arg2;
4690 	MATCHMAP *mp = (MATCHMAP *)arg3;
4691 	NODELIST *ndlp = (NODELIST *)arg4;
4692 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
4693 	uint8_t *bp;
4694 	uint32_t *lp;
4695 	uint32_t msglen;
4696 	uint8_t *tmp;
4697 
4698 	uint8_t ReasonCode;
4699 	uint8_t ReasonCodeExplanation;
4700 	AUTH_MSG_HDR *msg;
4701 	uint8_t *temp;
4702 	uint32_t rc, i, hs_id[2], dh_id[5];
4703 					/* from initiator */
4704 	uint32_t hash_id, dhgp_id;	/* to be used by responder */
4705 	uint16_t num_hs = 0;
4706 	uint16_t num_dh = 0;
4707 
4708 	/*
4709 	 * 1. process the auth msg, should acc first no matter what. 2.
4710 	 * return DHCHAP_Challenge for AUTH_Negotiate auth msg, AUTH_Reject
4711 	 * for anything else.
4712 	 */
4713 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4714 	    "rcv_auth_msg_unmapped_node: Sending ACC: did=0x%x",
4715 	    ndlp->nlp_DID);
4716 
4717 	(void) emlxs_els_reply(port, iocbq, ELS_CMD_ACC, ELS_CMD_AUTH, 0, 0);
4718 
4719 	bp = mp->virt;
4720 	lp = (uint32_t *)bp;
4721 
4722 	msg = (AUTH_MSG_HDR *)((uint8_t *)lp);
4723 	msglen = msg->msg_len;
4724 
4725 	tmp = ((uint8_t *)lp);
4726 
4727 	/* temp is used for error checking */
4728 	temp = (uint8_t *)((uint8_t *)lp);
4729 	/* Check the auth_els_code */
4730 	if (((*(uint32_t *)temp) & 0xFFFFFFFF) != LE_SWAP32(0x90000B01)) {
4731 		ReasonCode = AUTHRJT_FAILURE;
4732 		ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD;
4733 
4734 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4735 		    "rcv_auth_msg_unmapped_node: payload(1)=0x%x",
4736 		    (*(uint32_t *)temp));
4737 
4738 		goto AUTH_Reject;
4739 	}
4740 	temp += 3 * sizeof (uint32_t);
4741 	/* Check name tag and name length */
4742 	if (((*(uint32_t *)temp) & 0xFFFFFFFF) != LE_SWAP32(0x00010008)) {
4743 		ReasonCode = AUTHRJT_FAILURE;
4744 		ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD;
4745 
4746 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4747 		    "rcv_auth_msg_unmapped_node: payload(2)=0x%x",
4748 		    (*(uint32_t *)temp));
4749 
4750 		goto AUTH_Reject;
4751 	}
4752 	temp += sizeof (uint32_t) + 8;
4753 	/* Check proto_num */
4754 	if (((*(uint32_t *)temp) & 0xFFFFFFFF) != LE_SWAP32(0x00000001)) {
4755 		ReasonCode = AUTHRJT_FAILURE;
4756 		ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD;
4757 
4758 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4759 		    "rcv_auth_msg_unmapped_node: payload(3)=0x%x",
4760 		    (*(uint32_t *)temp));
4761 
4762 		goto AUTH_Reject;
4763 	}
4764 	temp += sizeof (uint32_t);
4765 
4766 	/* Get para_len */
4767 	/* para_len = *(uint32_t *)temp; */
4768 	temp += sizeof (uint32_t);
4769 
4770 	/* Check proto_id */
4771 	if (((*(uint32_t *)temp) & 0xFFFFFFFF) != AUTH_DHCHAP) {
4772 		ReasonCode = AUTHRJT_FAILURE;
4773 		ReasonCodeExplanation = AUTHEXP_BAD_PROTOCOL;
4774 
4775 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4776 		    "rcv_auth_msg_unmapped_node: payload(4)=0x%x",
4777 		    (*(uint32_t *)temp));
4778 
4779 		goto AUTH_Reject;
4780 	}
4781 	temp += sizeof (uint32_t);
4782 	/* Check hashlist tag */
4783 	if ((LE_SWAP32(*(uint32_t *)temp) & 0xFFFF0000) >> 16 !=
4784 	    LE_SWAP16(HASH_LIST_TAG)) {
4785 		ReasonCode = AUTHRJT_FAILURE;
4786 		ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD;
4787 
4788 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4789 		    "rcv_auth_msg_unmapped_node: payload(5)=0x%x",
4790 		    (LE_SWAP32(*(uint32_t *)temp) & 0xFFFF0000) >> 16);
4791 
4792 		goto AUTH_Reject;
4793 	}
4794 	/* Get num_hs  */
4795 	num_hs = LE_SWAP32(*(uint32_t *)temp) & 0x0000FFFF;
4796 
4797 	temp += sizeof (uint32_t);
4798 	/* Check HashList_value1 */
4799 	hs_id[0] = *(uint32_t *)temp;
4800 
4801 	if ((hs_id[0] != AUTH_MD5) && (hs_id[0] != AUTH_SHA1)) {
4802 		ReasonCode = AUTHRJT_LOGIC_ERR;
4803 		ReasonCodeExplanation = AUTHEXP_HASHFUNC_UNUSABLE;
4804 
4805 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4806 		    "rcv_auth_msg_unmapped_node: payload(6)=0x%x",
4807 		    (*(uint32_t *)temp));
4808 
4809 		goto AUTH_Reject;
4810 	}
4811 	if (num_hs == 1) {
4812 		hs_id[1] = 0;
4813 	} else if (num_hs == 2) {
4814 		temp += sizeof (uint32_t);
4815 		hs_id[1] = *(uint32_t *)temp;
4816 
4817 		if ((hs_id[1] != AUTH_MD5) && (hs_id[1] != AUTH_SHA1)) {
4818 			ReasonCode = AUTHRJT_LOGIC_ERR;
4819 			ReasonCodeExplanation = AUTHEXP_HASHFUNC_UNUSABLE;
4820 
4821 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4822 			    "rcv_auth_msg_unmapped_node: payload(7)=0x%x",
4823 			    (*(uint32_t *)temp));
4824 
4825 			goto AUTH_Reject;
4826 		}
4827 		if (hs_id[0] == hs_id[1]) {
4828 			ReasonCode = AUTHRJT_FAILURE;
4829 			ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD;
4830 
4831 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4832 			    "rcv_auth_msg_unmapped_node: payload(8)=0x%x",
4833 			    (*(uint32_t *)temp));
4834 
4835 			goto AUTH_Reject;
4836 		}
4837 	} else {
4838 		ReasonCode = AUTHRJT_FAILURE;
4839 		ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD;
4840 
4841 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4842 		    "rcv_auth_msg_unmapped_node: payload(9)=0x%x",
4843 		    (*(uint32_t *)(temp - sizeof (uint32_t))));
4844 
4845 		goto AUTH_Reject;
4846 	}
4847 
4848 	/* Which hash_id should we use */
4849 	if (num_hs == 1) {
4850 		/*
4851 		 * We always use the highest priority specified by us if we
4852 		 * match initiator's , Otherwise, we use the next higher we
4853 		 * both have. CR 26238
4854 		 */
4855 		if (node_dhc->auth_cfg.hash_priority[0] == hs_id[0]) {
4856 			hash_id = node_dhc->auth_cfg.hash_priority[0];
4857 		} else if (node_dhc->auth_cfg.hash_priority[1] == hs_id[0]) {
4858 			hash_id = node_dhc->auth_cfg.hash_priority[1];
4859 		} else {
4860 			ReasonCode = AUTHRJT_LOGIC_ERR;
4861 			ReasonCodeExplanation = AUTHEXP_HASHFUNC_UNUSABLE;
4862 
4863 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4864 			    "rcv_auth_msg_unmapped_node: pload(10)=0x%x",
4865 			    (*(uint32_t *)temp));
4866 
4867 			goto AUTH_Reject;
4868 		}
4869 	} else {
4870 		/*
4871 		 * Since the initiator specified two hashs, we always select
4872 		 * our first one.
4873 		 */
4874 		hash_id = node_dhc->auth_cfg.hash_priority[0];
4875 	}
4876 
4877 	temp += sizeof (uint32_t);
4878 	/* Check DHgIDList_tag */
4879 	if ((LE_SWAP32(*(uint32_t *)temp) & 0xFFFF0000) >> 16 !=
4880 	    LE_SWAP16(DHGID_LIST_TAG)) {
4881 		ReasonCode = AUTHRJT_FAILURE;
4882 		ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD;
4883 
4884 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4885 		    "rcv_auth_msg_unmapped_node: payload(11)=0x%x",
4886 		    (*(uint32_t *)temp));
4887 
4888 		goto AUTH_Reject;
4889 	}
4890 	/* Get num_dh */
4891 	num_dh = LE_SWAP32(*(uint32_t *)temp) & 0x0000FFFF;
4892 
4893 	if (num_dh == 0) {
4894 		ReasonCode = AUTHRJT_FAILURE;
4895 		ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD;
4896 
4897 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4898 		    "rcv_auth_msg_unmapped_node: payload(12)=0x%x",
4899 		    (*(uint32_t *)temp));
4900 
4901 		goto AUTH_Reject;
4902 	}
4903 	for (i = 0; i < num_dh; i++) {
4904 		temp += sizeof (uint32_t);
4905 		/* Check DHgIDList_g0 */
4906 		dh_id[i] = (*(uint32_t *)temp);
4907 	}
4908 
4909 	rc = emlxs_check_dhgp(port, ndlp, dh_id, num_dh, &dhgp_id);
4910 
4911 	if (rc == 1) {
4912 		ReasonCode = AUTHRJT_LOGIC_ERR;
4913 		ReasonCodeExplanation = AUTHEXP_DHGROUP_UNUSABLE;
4914 
4915 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4916 		    "rcv_auth_msg_unmapped_node: payload(13)=0x%x",
4917 		    (*(uint32_t *)temp));
4918 
4919 		goto AUTH_Reject;
4920 	} else if (rc == 2) {
4921 		ReasonCode = AUTHRJT_FAILURE;
4922 		ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD;
4923 
4924 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4925 		    "rcv_auth_msg_unmapped_node: payload(14)=0x%x",
4926 		    (*(uint32_t *)temp));
4927 
4928 		goto AUTH_Reject;
4929 	}
4930 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4931 	    "rcv_auth_msg_unmapped_node: 0x%x 0x%x 0x%x 0x%x 0x%x",
4932 	    hash_id, dhgp_id, msg->auth_msg_code, msglen, msg->tran_id);
4933 
4934 	/*
4935 	 * since ndlp is the initiator, tran_id is store in
4936 	 * nlp_auth_tranid_ini
4937 	 */
4938 	node_dhc->nlp_auth_tranid_ini = LE_SWAP32(msg->tran_id);
4939 
4940 	if (msg->auth_msg_code == AUTH_NEGOTIATE) {
4941 
4942 		/*
4943 		 * at this point, we know for sure we received the
4944 		 * auth-negotiate msg from another entity, so cancel the
4945 		 * auth-rsp timeout timer if we are expecting it. should
4946 		 * never happen?
4947 		 */
4948 		node_dhc->nlp_auth_flag = 1;
4949 
4950 		if (node_dhc->nlp_authrsp_tmo) {
4951 			node_dhc->nlp_authrsp_tmo = 0;
4952 		}
4953 		/*
4954 		 * If at this point, the host is doing reauthentication
4955 		 * (reauth heart beat) to this ndlp, then Host should remain
4956 		 * as the auth initiator, host should reply to the received
4957 		 * AUTH_Negotiate message with an AUTH_Reject message with
4958 		 * Reason Code 'Logical Error' and Reason Code Explanation
4959 		 * 'Authentication Transaction Already Started'.
4960 		 */
4961 		if (node_dhc->nlp_reauth_status ==
4962 		    NLP_HOST_REAUTH_IN_PROGRESS) {
4963 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4964 		    "rcv_auth_msg_unmapped_node: Ht reauth inprgress.");
4965 
4966 			ReasonCode = AUTHRJT_LOGIC_ERR;
4967 			ReasonCodeExplanation = AUTHEXP_AUTHTRAN_STARTED;
4968 
4969 			goto AUTH_Reject;
4970 		}
4971 		/* Send back the DHCHAP_Challenge with the proper paramaters */
4972 		if (emlxs_issue_dhchap_challenge(port, ndlp, 0, tmp,
4973 		    LE_SWAP32(msglen),
4974 		    hash_id, dhgp_id)) {
4975 
4976 			goto AUTH_Reject;
4977 		}
4978 		/* setup the proper state */
4979 		emlxs_dhc_state(port, ndlp,
4980 		    NODE_STATE_DHCHAP_CHALLENGE_ISSUE, 0, 0);
4981 
4982 	} else {
4983 		ReasonCode = AUTHRJT_FAILURE;
4984 		ReasonCodeExplanation = AUTHEXP_BAD_PROTOCOL;
4985 
4986 		goto AUTH_Reject;
4987 	}
4988 
4989 	return (node_dhc->state);
4990 
4991 AUTH_Reject:
4992 
4993 	emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_FAILED,
4994 	    ReasonCode, ReasonCodeExplanation);
4995 	(void) emlxs_issue_auth_reject(port, ndlp, 0, 0, ReasonCode,
4996 	    ReasonCodeExplanation);
4997 	emlxs_dhc_auth_complete(port, ndlp, 1);
4998 
4999 	return (node_dhc->state);
5000 
5001 } /* emlxs_rcv_auth_msg_unmapped_node */
5002 
5003 
5004 
5005 
5006 /*
5007  * emlxs_hash_vrf for verification only the host is the initiator in
5008  * the routine.
5009  */
5010 /* ARGSUSED */
5011 static uint32_t *
emlxs_hash_vrf(emlxs_port_t * port,emlxs_port_dhc_t * port_dhc,NODELIST * ndlp,uint32_t tran_id,union challenge_val un_cval)5012 emlxs_hash_vrf(
5013 	emlxs_port_t *port,
5014 	emlxs_port_dhc_t *port_dhc,
5015 	NODELIST *ndlp,
5016 	uint32_t tran_id,
5017 	union challenge_val un_cval)
5018 {
5019 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
5020 	uint32_t dhgp_id;
5021 	uint32_t hash_id;
5022 	uint32_t *hash_val;
5023 	uint32_t hash_size;
5024 	MD5_CTX mdctx;
5025 	SHA1_CTX sha1ctx;
5026 	uint8_t sha1_digest[20];
5027 	uint8_t md5_digest[16];
5028 	uint8_t mytran_id = 0x00;
5029 
5030 	char *remote_key;
5031 
5032 	tran_id = (AUTH_TRAN_ID_MASK & tran_id);
5033 	mytran_id = (uint8_t)(LE_SWAP32(tran_id));
5034 
5035 
5036 	if (ndlp->nlp_DID == FABRIC_DID) {
5037 		remote_key = (char *)node_dhc->auth_key.remote_password;
5038 		hash_id = node_dhc->hash_id;
5039 		dhgp_id = node_dhc->dhgp_id;
5040 	} else {
5041 		remote_key = (char *)node_dhc->auth_key.remote_password;
5042 		hash_id = node_dhc->nlp_auth_hashid;
5043 		dhgp_id = node_dhc->nlp_auth_dhgpid;
5044 	}
5045 
5046 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
5047 	    "hash_vrf: 0x%x 0x%x 0x%x tran_id=0x%x",
5048 	    ndlp->nlp_DID, hash_id, dhgp_id, mytran_id);
5049 
5050 	if (dhgp_id == 0) {
5051 		/* NULL DHCHAP */
5052 		if (hash_id == AUTH_MD5) {
5053 			bzero(&mdctx, sizeof (MD5_CTX));
5054 
5055 			hash_size = MD5_LEN;
5056 
5057 			MD5Init(&mdctx);
5058 
5059 			/* Transaction Identifier T */
5060 			MD5Update(&mdctx, (unsigned char *) &mytran_id, 1);
5061 
5062 			MD5Update(&mdctx, (unsigned char *) remote_key,
5063 			    node_dhc->auth_key.remote_password_length);
5064 
5065 			/* Augmented challenge: NULL DHCHAP i.e., Challenge */
5066 			MD5Update(&mdctx,
5067 			    (unsigned char *)&(un_cval.md5.val[0]), MD5_LEN);
5068 
5069 			MD5Final((uint8_t *)md5_digest, &mdctx);
5070 
5071 			hash_val = (uint32_t *)kmem_alloc(hash_size,
5072 			    KM_NOSLEEP);
5073 			if (hash_val == NULL) {
5074 				return (NULL);
5075 			} else {
5076 				bcopy((void *)&md5_digest,
5077 				    (void *)hash_val, MD5_LEN);
5078 			}
5079 			/*
5080 			 * emlxs_md5_digest_to_hex((uint8_t *)hash_val,
5081 			 * output);
5082 			 */
5083 		}
5084 		if (hash_id == AUTH_SHA1) {
5085 			bzero(&sha1ctx, sizeof (SHA1_CTX));
5086 			hash_size = SHA1_LEN;
5087 			SHA1Init(&sha1ctx);
5088 
5089 			SHA1Update(&sha1ctx, (void *)&mytran_id, 1);
5090 
5091 			SHA1Update(&sha1ctx, (void *)remote_key,
5092 			    node_dhc->auth_key.remote_password_length);
5093 
5094 			SHA1Update(&sha1ctx,
5095 			    (void *)&(un_cval.sha1.val[0]), SHA1_LEN);
5096 
5097 			SHA1Final((void *)sha1_digest, &sha1ctx);
5098 
5099 			/*
5100 			 * emlxs_sha1_digest_to_hex((uint8_t *)hash_val,
5101 			 * output);
5102 			 */
5103 
5104 			hash_val = (uint32_t *)kmem_alloc(hash_size,
5105 			    KM_NOSLEEP);
5106 			if (hash_val == NULL) {
5107 				return (NULL);
5108 			} else {
5109 				bcopy((void *)&sha1_digest,
5110 				    (void *)hash_val, SHA1_LEN);
5111 			}
5112 		}
5113 		return ((uint32_t *)hash_val);
5114 	} else {
5115 		/* Verification of bi-dir auth for DH-CHAP group */
5116 		/* original challenge is node_dhc->bi_cval[] */
5117 		/* session key is node_dhc->ses_key[] */
5118 		/* That's IT */
5119 		/*
5120 		 * H(bi_cval || ses_key) = C H(Ti || Km || C)  = hash_val
5121 		 */
5122 		if (hash_id == AUTH_MD5) {
5123 			bzero(&mdctx, sizeof (MD5_CTX));
5124 			hash_size = MD5_LEN;
5125 
5126 			MD5Init(&mdctx);
5127 
5128 			MD5Update(&mdctx,
5129 			    (void *)&(un_cval.md5.val[0]), MD5_LEN);
5130 
5131 			if (ndlp->nlp_DID == FABRIC_DID) {
5132 				MD5Update(&mdctx,
5133 				    (void *)&node_dhc->ses_key[0],
5134 				    node_dhc->seskey_len);
5135 			} else {
5136 				/* ses_key is obtained in emlxs_hash_rsp */
5137 				MD5Update(&mdctx,
5138 				    (void *)&node_dhc->nlp_auth_misc.ses_key[0],
5139 				    node_dhc->nlp_auth_misc.seskey_len);
5140 			}
5141 
5142 			MD5Final((void *)md5_digest, &mdctx);
5143 
5144 			MD5Init(&mdctx);
5145 
5146 			MD5Update(&mdctx, (void *)&mytran_id, 1);
5147 
5148 			MD5Update(&mdctx, (void *)remote_key,
5149 			    node_dhc->auth_key.remote_password_length);
5150 
5151 			MD5Update(&mdctx, (void *)md5_digest, MD5_LEN);
5152 
5153 			MD5Final((void *)md5_digest, &mdctx);
5154 
5155 			hash_val = (uint32_t *)kmem_alloc(hash_size,
5156 			    KM_NOSLEEP);
5157 			if (hash_val == NULL) {
5158 				return (NULL);
5159 			} else {
5160 				bcopy((void *)&md5_digest,
5161 				    (void *)hash_val, MD5_LEN);
5162 			}
5163 		}
5164 		if (hash_id == AUTH_SHA1) {
5165 			bzero(&sha1ctx, sizeof (SHA1_CTX));
5166 			hash_size = SHA1_LEN;
5167 
5168 			SHA1Init(&sha1ctx);
5169 
5170 			SHA1Update(&sha1ctx,
5171 			    (void *)&(un_cval.sha1.val[0]), SHA1_LEN);
5172 
5173 			if (ndlp->nlp_DID == FABRIC_DID) {
5174 				SHA1Update(&sha1ctx,
5175 				    (void *)&node_dhc->ses_key[0],
5176 				    node_dhc->seskey_len);
5177 			} else {
5178 				/* ses_key was obtained in emlxs_hash_rsp */
5179 				SHA1Update(&sha1ctx,
5180 				    (void *)&node_dhc->nlp_auth_misc.ses_key[0],
5181 				    node_dhc->nlp_auth_misc.seskey_len);
5182 			}
5183 
5184 			SHA1Final((void *)sha1_digest, &sha1ctx);
5185 
5186 			SHA1Init(&sha1ctx);
5187 
5188 			SHA1Update(&sha1ctx, (void *)&mytran_id, 1);
5189 
5190 			SHA1Update(&sha1ctx, (void *)remote_key,
5191 			    node_dhc->auth_key.remote_password_length);
5192 
5193 			SHA1Update(&sha1ctx, (void *)sha1_digest, SHA1_LEN);
5194 
5195 			SHA1Final((void *)sha1_digest, &sha1ctx);
5196 
5197 			hash_val = (uint32_t *)kmem_alloc(hash_size,
5198 			    KM_NOSLEEP);
5199 			if (hash_val == NULL) {
5200 				return (NULL);
5201 			} else {
5202 				bcopy((void *)&sha1_digest,
5203 				    (void *)hash_val, SHA1_LEN);
5204 			}
5205 		}
5206 		return ((uint32_t *)hash_val);
5207 	}
5208 
5209 } /* emlxs_hash_vrf */
5210 
5211 
5212 /*
5213  * If dhval == NULL, NULL DHCHAP else, DHCHAP group.
5214  *
5215  * This routine is used by the auth transaction initiator (Who does the
5216  * auth-negotiate) to calculate the R1 (response) based on
5217  * the dh value it received, its own random private key, the challenge it
5218  * received, and Transaction id, as well as the password
5219  * associated with this very initiator in the auth pair.
5220  */
5221 uint32_t *
emlxs_hash_rsp(emlxs_port_t * port,emlxs_port_dhc_t * port_dhc,NODELIST * ndlp,uint32_t tran_id,union challenge_val un_cval,uint8_t * dhval,uint32_t dhvallen)5222 emlxs_hash_rsp(
5223 emlxs_port_t *port,
5224 emlxs_port_dhc_t *port_dhc,
5225 NODELIST *ndlp,
5226 uint32_t tran_id,
5227 union challenge_val un_cval,
5228 uint8_t *dhval,
5229 uint32_t dhvallen)
5230 {
5231 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
5232 	uint32_t dhgp_id;
5233 	uint32_t hash_id;
5234 	uint32_t *hash_val;
5235 	uint32_t hash_size;
5236 	MD5_CTX mdctx;
5237 	SHA1_CTX sha1ctx;
5238 	uint8_t sha1_digest[20];
5239 	uint8_t md5_digest[16];
5240 	uint8_t Cai[20];
5241 	uint8_t mytran_id = 0x00;
5242 	char *mykey;
5243 	BIG_ERR_CODE err = BIG_OK;
5244 
5245 	if (ndlp->nlp_DID == FABRIC_DID) {
5246 		hash_id = node_dhc->hash_id;
5247 		dhgp_id = node_dhc->dhgp_id;
5248 	} else {
5249 		hash_id = node_dhc->nlp_auth_hashid;
5250 		dhgp_id = node_dhc->nlp_auth_dhgpid;
5251 	}
5252 
5253 	tran_id = (AUTH_TRAN_ID_MASK & tran_id);
5254 	mytran_id = (uint8_t)(LE_SWAP32(tran_id));
5255 
5256 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
5257 	    "hash_rsp: 0x%x 0x%x 0x%x 0x%x dhvallen=0x%x",
5258 	    ndlp->nlp_DID, hash_id, dhgp_id, mytran_id, dhvallen);
5259 
5260 	if (ndlp->nlp_DID == FABRIC_DID) {
5261 		mykey = (char *)node_dhc->auth_key.local_password;
5262 
5263 	} else {
5264 		mykey = (char *)node_dhc->auth_key.local_password;
5265 	}
5266 
5267 	if (dhval == NULL) {
5268 		/* NULL DHCHAP */
5269 		if (hash_id == AUTH_MD5) {
5270 			bzero(&mdctx, sizeof (MD5_CTX));
5271 			hash_size = MD5_LEN;
5272 
5273 			MD5Init(&mdctx);
5274 
5275 			MD5Update(&mdctx, (unsigned char *)&mytran_id, 1);
5276 
5277 			MD5Update(&mdctx, (unsigned char *)mykey,
5278 			    node_dhc->auth_key.local_password_length);
5279 
5280 			MD5Update(&mdctx,
5281 			    (unsigned char *)&(un_cval.md5.val[0]),
5282 			    MD5_LEN);
5283 
5284 			MD5Final((uint8_t *)md5_digest, &mdctx);
5285 
5286 			hash_val = (uint32_t *)kmem_alloc(hash_size,
5287 			    KM_NOSLEEP);
5288 			if (hash_val == NULL) {
5289 				return (NULL);
5290 			} else {
5291 				bcopy((void *)&md5_digest,
5292 				    (void *)hash_val, MD5_LEN);
5293 			}
5294 
5295 			/*
5296 			 * emlxs_md5_digest_to_hex((uint8_t *)hash_val,
5297 			 * output);
5298 			 */
5299 
5300 		}
5301 		if (hash_id == AUTH_SHA1) {
5302 			bzero(&sha1ctx, sizeof (SHA1_CTX));
5303 			hash_size = SHA1_LEN;
5304 			SHA1Init(&sha1ctx);
5305 
5306 			SHA1Update(&sha1ctx, (void *)&mytran_id, 1);
5307 
5308 			SHA1Update(&sha1ctx, (void *)mykey,
5309 			    node_dhc->auth_key.local_password_length);
5310 
5311 			SHA1Update(&sha1ctx,
5312 			    (void *)&(un_cval.sha1.val[0]), SHA1_LEN);
5313 
5314 			SHA1Final((void *)sha1_digest, &sha1ctx);
5315 
5316 			/*
5317 			 * emlxs_sha1_digest_to_hex((uint8_t *)hash_val,
5318 			 * output);
5319 			 */
5320 
5321 			hash_val = (uint32_t *)kmem_alloc(hash_size,
5322 			    KM_NOSLEEP);
5323 			if (hash_val == NULL) {
5324 				return (NULL);
5325 			} else {
5326 				bcopy((void *)&sha1_digest,
5327 				    (void *)hash_val, SHA1_LEN);
5328 			}
5329 		}
5330 		return ((uint32_t *)hash_val);
5331 	} else {
5332 
5333 		/* process DH grops */
5334 		/*
5335 		 * calculate interm hash value Ca1 Ca1 = H(C1 || (g^x mod
5336 		 * p)^y mod p) in which C1 is the challenge received. g^x mod
5337 		 * p is the dhval received y is the random number in 16 bytes
5338 		 * for MD5, 20 bytes for SHA1 p is hardcoded value based on
5339 		 * different DH groups.
5340 		 *
5341 		 * To calculate hash value R1 R1 = H (Ti || Kn || Cai) in which
5342 		 * Ti is the transaction identifier Kn is the shared secret.
5343 		 * Cai is the result from interm hash.
5344 		 *
5345 		 * g^y mod p is reserved in port_dhc as pubkey (public key).for
5346 		 * bi-dir challenge is another random number. y is prikey
5347 		 * (private key). ((g^x mod p)^y mod p) is sekey (session
5348 		 * key)
5349 		 */
5350 		err = emlxs_interm_hash(port, port_dhc, ndlp,
5351 		    (void *)&Cai, tran_id,
5352 		    un_cval, dhval, &dhvallen);
5353 
5354 		if (err != BIG_OK) {
5355 			return (NULL);
5356 		}
5357 		if (hash_id == AUTH_MD5) {
5358 			bzero(&mdctx, sizeof (MD5_CTX));
5359 			hash_size = MD5_LEN;
5360 
5361 			MD5Init(&mdctx);
5362 
5363 			MD5Update(&mdctx, (unsigned char *)&mytran_id, 1);
5364 
5365 			MD5Update(&mdctx, (unsigned char *)mykey,
5366 			    node_dhc->auth_key.local_password_length);
5367 
5368 			MD5Update(&mdctx, (unsigned char *)Cai, MD5_LEN);
5369 
5370 			MD5Final((uint8_t *)md5_digest, &mdctx);
5371 
5372 			hash_val = (uint32_t *)kmem_alloc(hash_size,
5373 			    KM_NOSLEEP);
5374 			if (hash_val == NULL) {
5375 				return (NULL);
5376 			} else {
5377 				bcopy((void *)&md5_digest,
5378 				    (void *)hash_val, MD5_LEN);
5379 			}
5380 		}
5381 		if (hash_id == AUTH_SHA1) {
5382 			bzero(&sha1ctx, sizeof (SHA1_CTX));
5383 			hash_size = SHA1_LEN;
5384 
5385 			SHA1Init(&sha1ctx);
5386 
5387 			SHA1Update(&sha1ctx, (void *)&mytran_id, 1);
5388 
5389 			SHA1Update(&sha1ctx, (void *)mykey,
5390 			    node_dhc->auth_key.local_password_length);
5391 
5392 			SHA1Update(&sha1ctx, (void *)&Cai[0], SHA1_LEN);
5393 
5394 			SHA1Final((void *)sha1_digest, &sha1ctx);
5395 
5396 			hash_val = (uint32_t *)kmem_alloc(hash_size,
5397 			    KM_NOSLEEP);
5398 			if (hash_val == NULL) {
5399 				return (NULL);
5400 			} else {
5401 				bcopy((void *)&sha1_digest,
5402 				    (void *)hash_val, SHA1_LEN);
5403 			}
5404 		}
5405 		return ((uint32_t *)hash_val);
5406 	}
5407 
5408 } /* emlxs_hash_rsp */
5409 
5410 
5411 /*
5412  * To get the augmented challenge Cai Stored in hash_val
5413  *
5414  * Cai = Hash (C1 || ((g^x mod p)^y mod p)) = Hash (C1 || (g^(x*y) mod p)
5415  *
5416  * C1:challenge received from the remote entity (g^x mod p): dh val
5417  * received from the remote entity (remote entity's pubkey) y:
5418  * random private key from the local entity Hash: hash function used in
5419  * agreement. (g^(x*y) mod p): shared session key (aka
5420  * shared secret) (g^y mod p): local entity's pubkey
5421  */
5422 /* ARGSUSED */
5423 BIG_ERR_CODE
emlxs_interm_hash(emlxs_port_t * port,emlxs_port_dhc_t * port_dhc,NODELIST * ndlp,void * hash_val,uint32_t tran_id,union challenge_val un_cval,uint8_t * dhval,uint32_t * dhvallen)5424 emlxs_interm_hash(
5425 emlxs_port_t *port,
5426 emlxs_port_dhc_t *port_dhc,
5427 NODELIST *ndlp,
5428 void *hash_val,
5429 uint32_t tran_id,
5430 union challenge_val un_cval,
5431 uint8_t *dhval,
5432 uint32_t *dhvallen)
5433 {
5434 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
5435 	uint32_t dhgp_id;
5436 	uint32_t hash_id;
5437 	MD5_CTX mdctx;
5438 	SHA1_CTX sha1ctx;
5439 	uint8_t sha1_digest[20];
5440 	uint8_t md5_digest[16];
5441 	uint32_t hash_size;
5442 	BIG_ERR_CODE err = BIG_OK;
5443 
5444 	if (ndlp->nlp_DID == FABRIC_DID) {
5445 		hash_id = node_dhc->hash_id;
5446 		dhgp_id = node_dhc->dhgp_id;
5447 	} else {
5448 		hash_id = node_dhc->nlp_auth_hashid;
5449 		dhgp_id = node_dhc->nlp_auth_dhgpid;
5450 	}
5451 
5452 	if (hash_id == AUTH_MD5) {
5453 		bzero(&mdctx, sizeof (MD5_CTX));
5454 		hash_size = MD5_LEN;
5455 		MD5Init(&mdctx);
5456 		MD5Update(&mdctx,
5457 		    (unsigned char *)&(un_cval.md5.val[0]), MD5_LEN);
5458 
5459 		/*
5460 		 * get the pub key (g^y mod p) and session key (g^(x*y) mod
5461 		 * p) and stored them in the partner's ndlp structure
5462 		 */
5463 		err = emlxs_BIGNUM_get_pubkey(port, port_dhc, ndlp,
5464 		    dhval, dhvallen, hash_size, dhgp_id);
5465 
5466 		if (err != BIG_OK) {
5467 			return (err);
5468 		}
5469 		if (ndlp->nlp_DID == FABRIC_DID) {
5470 			MD5Update(&mdctx,
5471 			    (unsigned char *)&node_dhc->ses_key[0],
5472 			    node_dhc->seskey_len);
5473 		} else {
5474 		MD5Update(&mdctx,
5475 		    (unsigned char *)&node_dhc->nlp_auth_misc.ses_key[0],
5476 		    node_dhc->nlp_auth_misc.seskey_len);
5477 		}
5478 
5479 		MD5Final((uint8_t *)md5_digest, &mdctx);
5480 
5481 		bcopy((void *)&md5_digest, (void *)hash_val, MD5_LEN);
5482 	}
5483 	if (hash_id == AUTH_SHA1) {
5484 		bzero(&sha1ctx, sizeof (SHA1_CTX));
5485 
5486 		hash_size = SHA1_LEN;
5487 
5488 		SHA1Init(&sha1ctx);
5489 
5490 		SHA1Update(&sha1ctx, (void *)&(un_cval.sha1.val[0]), SHA1_LEN);
5491 
5492 		/* get the pub key and session key */
5493 		err = emlxs_BIGNUM_get_pubkey(port, port_dhc, ndlp,
5494 		    dhval, dhvallen, hash_size, dhgp_id);
5495 
5496 		if (err != BIG_OK) {
5497 			return (err);
5498 		}
5499 		if (ndlp->nlp_DID == FABRIC_DID) {
5500 			SHA1Update(&sha1ctx, (void *)&node_dhc->ses_key[0],
5501 			    node_dhc->seskey_len);
5502 		} else {
5503 			SHA1Update(&sha1ctx,
5504 			    (void *)&node_dhc->nlp_auth_misc.ses_key[0],
5505 			    node_dhc->nlp_auth_misc.seskey_len);
5506 		}
5507 
5508 		SHA1Final((void *)sha1_digest, &sha1ctx);
5509 
5510 		bcopy((void *)&sha1_digest, (void *)hash_val, SHA1_LEN);
5511 	}
5512 	return (err);
5513 
5514 } /* emlxs_interm_hash */
5515 
5516 /*
5517  * This routine get the pubkey and session key. these pubkey and session
5518  * key are stored in the partner's ndlp structure.
5519  */
5520 /* ARGSUSED */
5521 BIG_ERR_CODE
emlxs_BIGNUM_get_pubkey(emlxs_port_t * port,emlxs_port_dhc_t * port_dhc,NODELIST * ndlp,uint8_t * dhval,uint32_t * dhvallen,uint32_t hash_size,uint32_t dhgp_id)5522 emlxs_BIGNUM_get_pubkey(
5523 			emlxs_port_t *port,
5524 			emlxs_port_dhc_t *port_dhc,
5525 			NODELIST *ndlp,
5526 			uint8_t *dhval,
5527 			uint32_t *dhvallen,
5528 			uint32_t hash_size,
5529 			uint32_t dhgp_id)
5530 {
5531 	emlxs_hba_t *hba = HBA;
5532 
5533 	BIGNUM a, e, n, result;
5534 	uint32_t plen;
5535 	uint8_t random_number[20];
5536 	unsigned char *tmp = NULL;
5537 	BIGNUM g, result1;
5538 
5539 #ifdef BIGNUM_CHUNK_32
5540 	uint8_t gen[] = {0x00, 0x00, 0x00, 0x02};
5541 #else
5542 	uint8_t gen[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02};
5543 #endif /* BIGNUM_CHUNK_32 */
5544 
5545 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
5546 	BIG_ERR_CODE err = BIG_OK;
5547 
5548 	/*
5549 	 * compute a^e mod n assume a < n, n odd, result->value at least as
5550 	 * long as n->value.
5551 	 *
5552 	 * a is the public key received from responder. e is the private key
5553 	 * generated by me. n is the wellknown modulus.
5554 	 */
5555 
5556 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
5557 	    "BIGNUM_get_pubkey: 0x%x 0x%x 0x%x 0x%x",
5558 	    ndlp->nlp_DID, *dhvallen, hash_size, dhgp_id);
5559 
5560 	/* size should be in the unit of (BIG_CHUNK_TYPE) words */
5561 	if (big_init(&a, CHARLEN2BIGNUMLEN(*dhvallen))  != BIG_OK) {
5562 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5563 		    "BIGNUM_get_pubkey: big_init failed. a size=%d",
5564 		    CHARLEN2BIGNUMLEN(*dhvallen));
5565 
5566 		err = BIG_NO_MEM;
5567 		return (err);
5568 	}
5569 	/* a: (g^x mod p) */
5570 	/*
5571 	 * dhval is in big-endian format. This call converts from
5572 	 * byte-big-endian format to big number format (words in little
5573 	 * endian order, but bytes within the words big endian)
5574 	 */
5575 	bytestring2bignum(&a, (unsigned char *)dhval, *dhvallen);
5576 
5577 	if (big_init(&e, CHARLEN2BIGNUMLEN(hash_size)) != BIG_OK) {
5578 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5579 		    "BIGNUM_get_pubkey: big_init failed. e size=%d",
5580 		    CHARLEN2BIGNUMLEN(hash_size));
5581 
5582 		err = BIG_NO_MEM;
5583 		goto ret1;
5584 	}
5585 #ifdef RAND
5586 
5587 	bzero(&random_number, hash_size);
5588 
5589 	/* to get random private key: y */
5590 	/* remember y is short lived private key */
5591 	if (hba->rdn_flag == 1) {
5592 		emlxs_get_random_bytes(ndlp, random_number, 20);
5593 	} else {
5594 		(void) random_get_pseudo_bytes(random_number, hash_size);
5595 	}
5596 
5597 	/* e: y */
5598 	bytestring2bignum(&e, (unsigned char *)random_number, hash_size);
5599 
5600 #endif	/* RAND */
5601 
5602 #ifdef MYRAND
5603 	bytestring2bignum(&e, (unsigned char *)myrand, hash_size);
5604 
5605 	printf("myrand random_number as Y ================\n");
5606 	for (i = 0; i < 5; i++) {
5607 		for (j = 0; j < 4; j++) {
5608 			printf("%x", myrand[(i * 4) + j]);
5609 		}
5610 		printf("\n");
5611 	}
5612 #endif	/* MYRAND */
5613 
5614 	switch (dhgp_id) {
5615 	case GROUP_1024:
5616 		plen = 128;
5617 		tmp = dhgp1_pVal;
5618 		break;
5619 
5620 	case GROUP_1280:
5621 		plen = 160;
5622 		tmp = dhgp2_pVal;
5623 		break;
5624 
5625 	case GROUP_1536:
5626 		plen = 192;
5627 		tmp = dhgp3_pVal;
5628 		break;
5629 
5630 	case GROUP_2048:
5631 		plen = 256;
5632 		tmp = dhgp4_pVal;
5633 		break;
5634 	}
5635 
5636 	if (big_init(&n, CHARLEN2BIGNUMLEN(plen)) != BIG_OK) {
5637 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5638 		    "BIGNUM_get_pubkey: big_init failed. n size=%d",
5639 		    CHARLEN2BIGNUMLEN(plen));
5640 		err = BIG_NO_MEM;
5641 		goto ret2;
5642 	}
5643 	bytestring2bignum(&n, (unsigned char *)tmp, plen);
5644 
5645 	if (big_init(&result, CHARLEN2BIGNUMLEN(512)) != BIG_OK) {
5646 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5647 		    "BIGNUM_get_pubkey: big_init failed. result size=%d",
5648 		    CHARLEN2BIGNUMLEN(512));
5649 
5650 		err = BIG_NO_MEM;
5651 		goto ret3;
5652 	}
5653 	if (big_cmp_abs(&a, &n) > 0) {
5654 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5655 		    "BIGNUM_get_pubkey: big_cmp_abs error.");
5656 		err = BIG_GENERAL_ERR;
5657 		goto ret4;
5658 	}
5659 	/* perform computation on big numbers to get seskey  */
5660 	/* a^e mod n */
5661 	/* i.e., (g^x mod p)^y mod p  */
5662 
5663 	if (big_modexp(&result, &a, &e, &n, NULL) != BIG_OK) {
5664 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5665 		    "BIGNUM_get_pubkey: big_modexp result error");
5666 		err = BIG_NO_MEM;
5667 		goto ret4;
5668 	}
5669 	/* convert big number ses_key to bytestring */
5670 	if (ndlp->nlp_DID == FABRIC_DID) {
5671 		/*
5672 		 * This call converts from big number format to
5673 		 * byte-big-endian format. big number format is words in
5674 		 * little endian order, but bytes within words in native byte
5675 		 * order
5676 		 */
5677 		bignum2bytestring(node_dhc->ses_key, &result,
5678 		    sizeof (BIG_CHUNK_TYPE) * (result.len));
5679 		node_dhc->seskey_len = sizeof (BIG_CHUNK_TYPE) * (result.len);
5680 
5681 		/* we can store another copy in ndlp */
5682 		bignum2bytestring(node_dhc->nlp_auth_misc.ses_key, &result,
5683 		    sizeof (BIG_CHUNK_TYPE) * (result.len));
5684 		node_dhc->nlp_auth_misc.seskey_len =
5685 		    sizeof (BIG_CHUNK_TYPE) * (result.len);
5686 	} else {
5687 		/* for end-to-end auth */
5688 		bignum2bytestring(node_dhc->nlp_auth_misc.ses_key, &result,
5689 		    sizeof (BIG_CHUNK_TYPE) * (result.len));
5690 		node_dhc->nlp_auth_misc.seskey_len =
5691 		    sizeof (BIG_CHUNK_TYPE) * (result.len);
5692 	}
5693 
5694 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
5695 	    "BIGNUM_get_pubkey: after seskey cal: 0x%x 0x%x 0x%x",
5696 	    node_dhc->nlp_auth_misc.seskey_len, result.size, result.len);
5697 
5698 
5699 	/* to get pub_key: g^y mod p, g is 2 */
5700 
5701 	if (big_init(&g, 1) != BIG_OK) {
5702 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5703 		    "BIGNUM_get_pubkey: big_init failed. g size=1");
5704 
5705 		err = BIG_NO_MEM;
5706 		goto ret4;
5707 	}
5708 	if (big_init(&result1, CHARLEN2BIGNUMLEN(512)) != BIG_OK) {
5709 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5710 		    "BIGNUM_get_pubkey: big_init failed. result1 size=%d",
5711 		    CHARLEN2BIGNUMLEN(512));
5712 		err = BIG_NO_MEM;
5713 		goto ret5;
5714 	}
5715 
5716 	bytestring2bignum(&g,
5717 	    (unsigned char *)&gen, sizeof (BIG_CHUNK_TYPE));
5718 
5719 	if (big_modexp(&result1, &g, &e, &n, NULL) != BIG_OK) {
5720 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5721 		    "BIGNUM_get_pubkey: big_modexp result1 error");
5722 		err = BIG_NO_MEM;
5723 		goto ret6;
5724 	}
5725 	/* convert big number pub_key to bytestring */
5726 	if (ndlp->nlp_DID == FABRIC_DID) {
5727 
5728 		bignum2bytestring(node_dhc->pub_key, &result1,
5729 		    sizeof (BIG_CHUNK_TYPE) * (result1.len));
5730 		node_dhc->pubkey_len = (result1.len) * sizeof (BIG_CHUNK_TYPE);
5731 
5732 		/* save another copy in ndlp */
5733 		bignum2bytestring(node_dhc->nlp_auth_misc.pub_key, &result1,
5734 		    sizeof (BIG_CHUNK_TYPE) * (result1.len));
5735 		node_dhc->nlp_auth_misc.pubkey_len =
5736 		    (result1.len) * sizeof (BIG_CHUNK_TYPE);
5737 
5738 	} else {
5739 		/* for end-to-end auth */
5740 		bignum2bytestring(node_dhc->nlp_auth_misc.pub_key, &result1,
5741 		    sizeof (BIG_CHUNK_TYPE) * (result1.len));
5742 		node_dhc->nlp_auth_misc.pubkey_len =
5743 		    (result1.len) * sizeof (BIG_CHUNK_TYPE);
5744 	}
5745 
5746 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
5747 	    "BIGNUM_get_pubkey: after pubkey cal: 0x%x 0x%x 0x%x",
5748 	    node_dhc->nlp_auth_misc.pubkey_len, result1.size, result1.len);
5749 
5750 
5751 ret6:
5752 	big_finish(&result1);
5753 ret5:
5754 	big_finish(&g);
5755 ret4:
5756 	big_finish(&result);
5757 ret3:
5758 	big_finish(&n);
5759 ret2:
5760 	big_finish(&e);
5761 ret1:
5762 	big_finish(&a);
5763 
5764 	return (err);
5765 
5766 } /* emlxs_BIGNUM_get_pubkey */
5767 
5768 
5769 /*
5770  * g^x mod p x is the priv_key g and p are wellknow based on dhgp_id
5771  */
5772 /* ARGSUSED */
5773 static BIG_ERR_CODE
emlxs_BIGNUM_get_dhval(emlxs_port_t * port,emlxs_port_dhc_t * port_dhc,NODELIST * ndlp,uint8_t * dhval,uint32_t * dhval_len,uint32_t dhgp_id,uint8_t * priv_key,uint32_t privkey_len)5774 emlxs_BIGNUM_get_dhval(
5775 emlxs_port_t *port,
5776 emlxs_port_dhc_t *port_dhc,
5777 NODELIST *ndlp,
5778 uint8_t *dhval,
5779 uint32_t *dhval_len,
5780 uint32_t dhgp_id,
5781 uint8_t *priv_key,
5782 uint32_t privkey_len)
5783 {
5784 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
5785 	BIGNUM g, e, n, result1;
5786 	uint32_t plen;
5787 	unsigned char *tmp = NULL;
5788 
5789 #ifdef BIGNUM_CHUNK_32
5790 	uint8_t gen[] = {0x00, 0x00, 0x00, 0x02};
5791 #else
5792 	uint8_t gen[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02};
5793 #endif /* BIGNUM_CHUNK_32 */
5794 
5795 	BIG_ERR_CODE err = BIG_OK;
5796 
5797 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
5798 	    "BIGNUM_get_dhval: did=0x%x privkey_len=0x%x dhgp_id=0x%x",
5799 	    ndlp->nlp_DID, privkey_len, dhgp_id);
5800 
5801 	if (big_init(&result1, CHARLEN2BIGNUMLEN(512)) != BIG_OK) {
5802 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5803 		    "BIGNUM_get_dhval: big_init failed. result1 size=%d",
5804 		    CHARLEN2BIGNUMLEN(512));
5805 
5806 		err = BIG_NO_MEM;
5807 		return (err);
5808 	}
5809 	if (big_init(&g, 1) != BIG_OK) {
5810 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5811 		    "BIGNUM_get_dhval: big_init failed. g size=1");
5812 
5813 		err = BIG_NO_MEM;
5814 		goto ret1;
5815 	}
5816 	/* get g */
5817 	bytestring2bignum(&g, (unsigned char *)gen, sizeof (BIG_CHUNK_TYPE));
5818 
5819 	if (big_init(&e, CHARLEN2BIGNUMLEN(privkey_len)) != BIG_OK) {
5820 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5821 		    "BIGNUM_get_dhval: big_init failed. e size=%d",
5822 		    CHARLEN2BIGNUMLEN(privkey_len));
5823 
5824 		err = BIG_NO_MEM;
5825 		goto ret2;
5826 	}
5827 	/* get x */
5828 	bytestring2bignum(&e, (unsigned char *)priv_key, privkey_len);
5829 
5830 	switch (dhgp_id) {
5831 	case GROUP_1024:
5832 		plen = 128;
5833 		tmp = dhgp1_pVal;
5834 		break;
5835 
5836 	case GROUP_1280:
5837 		plen = 160;
5838 		tmp = dhgp2_pVal;
5839 		break;
5840 
5841 	case GROUP_1536:
5842 		plen = 192;
5843 		tmp = dhgp3_pVal;
5844 		break;
5845 
5846 	case GROUP_2048:
5847 		plen = 256;
5848 		tmp = dhgp4_pVal;
5849 		break;
5850 	}
5851 
5852 	if (big_init(&n, CHARLEN2BIGNUMLEN(plen)) != BIG_OK) {
5853 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5854 		    "BIGNUM_get_dhval: big_init failed. n size=%d",
5855 		    CHARLEN2BIGNUMLEN(plen));
5856 
5857 		err = BIG_NO_MEM;
5858 		goto ret3;
5859 	}
5860 	/* get p */
5861 	bytestring2bignum(&n, (unsigned char *)tmp, plen);
5862 
5863 	/* to cal: (g^x mod p) */
5864 	if (big_modexp(&result1, &g, &e, &n, NULL) != BIG_OK) {
5865 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5866 		    "BIGNUM_get_dhval: big_modexp result1 error");
5867 
5868 		err = BIG_GENERAL_ERR;
5869 		goto ret4;
5870 	}
5871 	/* convert big number pub_key to bytestring */
5872 	if (ndlp->nlp_DID == FABRIC_DID) {
5873 		bignum2bytestring(node_dhc->hrsp_pub_key, &result1,
5874 		    sizeof (BIG_CHUNK_TYPE) * (result1.len));
5875 		node_dhc->hrsp_pubkey_len =
5876 		    (result1.len) * sizeof (BIG_CHUNK_TYPE);
5877 
5878 		/* save another copy in partner's ndlp */
5879 		bignum2bytestring(node_dhc->nlp_auth_misc.hrsp_pub_key,
5880 		    &result1,
5881 		    sizeof (BIG_CHUNK_TYPE) * (result1.len));
5882 
5883 		node_dhc->nlp_auth_misc.hrsp_pubkey_len =
5884 		    (result1.len) * sizeof (BIG_CHUNK_TYPE);
5885 	} else {
5886 		bignum2bytestring(node_dhc->nlp_auth_misc.hrsp_pub_key,
5887 		    &result1,
5888 		    sizeof (BIG_CHUNK_TYPE) * (result1.len));
5889 		node_dhc->nlp_auth_misc.hrsp_pubkey_len =
5890 		    (result1.len) * sizeof (BIG_CHUNK_TYPE);
5891 	}
5892 
5893 
5894 	if (ndlp->nlp_DID == FABRIC_DID) {
5895 		bcopy((void *)node_dhc->hrsp_pub_key, (void *)dhval,
5896 		    node_dhc->hrsp_pubkey_len);
5897 	} else {
5898 		bcopy((void *)node_dhc->nlp_auth_misc.hrsp_pub_key,
5899 		    (void *)dhval,
5900 		    node_dhc->nlp_auth_misc.hrsp_pubkey_len);
5901 	}
5902 
5903 	*(uint32_t *)dhval_len = (result1.len) * sizeof (BIG_CHUNK_TYPE);
5904 
5905 
5906 ret4:
5907 	big_finish(&result1);
5908 ret3:
5909 	big_finish(&e);
5910 ret2:
5911 	big_finish(&n);
5912 ret1:
5913 	big_finish(&g);
5914 
5915 	return (err);
5916 
5917 } /* emlxs_BIGNUM_get_dhval */
5918 
5919 
5920 /*
5921  * to get ((g^y mod p)^x mod p) a^e mod n
5922  */
5923 BIG_ERR_CODE
emlxs_BIGNUM_pubkey(emlxs_port_t * port,void * pubkey,uint8_t * dhval,uint32_t dhvallen,uint8_t * key,uint32_t key_size,uint32_t dhgp_id,uint32_t * pubkeylen)5924 emlxs_BIGNUM_pubkey(
5925 		    emlxs_port_t *port,
5926 		    void *pubkey,
5927 		    uint8_t *dhval,	/* g^y mod p */
5928 		    uint32_t dhvallen,
5929 		    uint8_t *key,	/* x */
5930 		    uint32_t key_size,
5931 		    uint32_t dhgp_id,
5932 		    uint32_t *pubkeylen)
5933 {
5934 	BIGNUM a, e, n, result;
5935 	uint32_t plen;
5936 	unsigned char *tmp = NULL;
5937 	BIG_ERR_CODE err = BIG_OK;
5938 
5939 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
5940 	    "BIGNUM_pubkey: dhvallen=0x%x dhgp_id=0x%x",
5941 	    dhvallen, dhgp_id);
5942 
5943 	if (big_init(&a, CHARLEN2BIGNUMLEN(dhvallen)) != BIG_OK) {
5944 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5945 		    "BIGNUM_pubkey: big_init failed. a size=%d",
5946 		    CHARLEN2BIGNUMLEN(dhvallen));
5947 
5948 		err = BIG_NO_MEM;
5949 		return (err);
5950 	}
5951 	/* get g^y mod p */
5952 	bytestring2bignum(&a, (unsigned char *)dhval, dhvallen);
5953 
5954 	if (big_init(&e, CHARLEN2BIGNUMLEN(key_size)) != BIG_OK) {
5955 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5956 		    "BIGNUM_pubkey: big_init failed. e size=%d",
5957 		    CHARLEN2BIGNUMLEN(key_size));
5958 
5959 		err = BIG_NO_MEM;
5960 		goto ret1;
5961 	}
5962 	/* get x */
5963 	bytestring2bignum(&e, (unsigned char *)key, key_size);
5964 
5965 	switch (dhgp_id) {
5966 	case GROUP_1024:
5967 		plen = 128;
5968 		tmp = dhgp1_pVal;
5969 		break;
5970 
5971 	case GROUP_1280:
5972 		plen = 160;
5973 		tmp = dhgp2_pVal;
5974 		break;
5975 
5976 	case GROUP_1536:
5977 		plen = 192;
5978 		tmp = dhgp3_pVal;
5979 		break;
5980 
5981 	case GROUP_2048:
5982 		plen = 256;
5983 		tmp = dhgp4_pVal;
5984 		break;
5985 	}
5986 
5987 	if (big_init(&n, CHARLEN2BIGNUMLEN(plen)) != BIG_OK) {
5988 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5989 		    "BIGNUM_pubkey: big_init failed. n size=%d",
5990 		    CHARLEN2BIGNUMLEN(plen));
5991 
5992 		err = BIG_NO_MEM;
5993 		goto ret2;
5994 	}
5995 	bytestring2bignum(&n, (unsigned char *)tmp, plen);
5996 
5997 	if (big_init(&result, CHARLEN2BIGNUMLEN(512)) != BIG_OK) {
5998 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5999 		    "BIGNUM_pubkey: big_init failed. result size=%d",
6000 		    CHARLEN2BIGNUMLEN(512));
6001 
6002 		err = BIG_NO_MEM;
6003 		goto ret3;
6004 	}
6005 	if (big_cmp_abs(&a, &n) > 0) {
6006 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
6007 		    "BIGNUM_pubkey: big_cmp_abs error");
6008 
6009 		err = BIG_GENERAL_ERR;
6010 		goto ret4;
6011 	}
6012 	if (big_modexp(&result, &a, &e, &n, NULL) != BIG_OK) {
6013 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
6014 		    "BIGNUM_pubkey: big_modexp result error");
6015 
6016 		err = BIG_NO_MEM;
6017 		goto ret4;
6018 	}
6019 	bignum2bytestring(pubkey, &result,
6020 	    sizeof (BIG_CHUNK_TYPE) * (result.len));
6021 	*pubkeylen = sizeof (BIG_CHUNK_TYPE) * (result.len);
6022 
6023 	/* This pubkey is actually session key */
6024 
6025 ret4:
6026 	big_finish(&result);
6027 ret3:
6028 	big_finish(&n);
6029 ret2:
6030 	big_finish(&e);
6031 ret1:
6032 	big_finish(&a);
6033 
6034 	return (err);
6035 
6036 } /* emlxs_BIGNUM_pubkey */
6037 
6038 
6039 /*
6040  * key: x dhval: (g^y mod p) tran_id: Ti bi_cval: C2 hash_id: H dhgp_id: p/g
6041  *
6042  * Cai = H (C2 || ((g^y mod p)^x mod p) )
6043  *
6044  */
6045 /* ARGSUSED */
6046 BIG_ERR_CODE
emlxs_hash_Cai(emlxs_port_t * port,emlxs_port_dhc_t * port_dhc,NODELIST * ndlp,void * Cai,uint32_t hash_id,uint32_t dhgp_id,uint32_t tran_id,uint8_t * cval,uint32_t cval_len,uint8_t * key,uint8_t * dhval,uint32_t dhvallen)6047 emlxs_hash_Cai(
6048 	emlxs_port_t *port,
6049 	emlxs_port_dhc_t *port_dhc,
6050 	NODELIST *ndlp,
6051 	void *Cai,
6052 	uint32_t hash_id,
6053 	uint32_t dhgp_id,
6054 	uint32_t tran_id,
6055 	uint8_t *cval,
6056 	uint32_t cval_len,
6057 	uint8_t *key,
6058 	uint8_t *dhval,
6059 	uint32_t dhvallen)
6060 {
6061 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
6062 	MD5_CTX mdctx;
6063 	SHA1_CTX sha1ctx;
6064 	uint8_t sha1_digest[20];
6065 	uint8_t md5_digest[16];
6066 	uint8_t pubkey[512];
6067 	uint32_t pubkey_len = 0;
6068 	uint32_t key_size;
6069 	BIG_ERR_CODE err = BIG_OK;
6070 
6071 	key_size = cval_len;
6072 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
6073 	    "hash_Cai: 0x%x 0x%x 0x%x 0x%x 0x%x",
6074 	    ndlp->nlp_DID, hash_id, dhgp_id, tran_id, dhvallen);
6075 
6076 	if (hash_id == AUTH_MD5) {
6077 		bzero(&mdctx, sizeof (MD5_CTX));
6078 		MD5Init(&mdctx);
6079 		MD5Update(&mdctx, (unsigned char *)cval, cval_len);
6080 
6081 		/* this pubkey obtained is actually the session key */
6082 		/*
6083 		 * pubkey: ((g^y mod p)^x mod p)
6084 		 */
6085 		err = emlxs_BIGNUM_pubkey(port, pubkey, dhval, dhvallen,
6086 		    key, key_size, dhgp_id, &pubkey_len);
6087 
6088 		if (err != BIG_OK) {
6089 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
6090 			    "hash_Cai: MD5 BIGNUM_pubkey error: 0x%x",
6091 			    err);
6092 
6093 			err = BIG_GENERAL_ERR;
6094 			return (err);
6095 		}
6096 		if (pubkey_len == 0) {
6097 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
6098 			    "hash_Cai: MD5 BIGNUM_pubkey error: len=0");
6099 
6100 			err = BIG_GENERAL_ERR;
6101 			return (err);
6102 		}
6103 		if (ndlp->nlp_DID == FABRIC_DID) {
6104 			bcopy((void *)pubkey,
6105 			    (void *)node_dhc->hrsp_ses_key, pubkey_len);
6106 			node_dhc->hrsp_seskey_len = pubkey_len;
6107 
6108 			/* store extra copy */
6109 			bcopy((void *)pubkey,
6110 			    (void *)node_dhc->nlp_auth_misc.hrsp_ses_key,
6111 			    pubkey_len);
6112 			node_dhc->nlp_auth_misc.hrsp_seskey_len = pubkey_len;
6113 
6114 		} else {
6115 			bcopy((void *)pubkey,
6116 			    (void *)node_dhc->nlp_auth_misc.hrsp_ses_key,
6117 			    pubkey_len);
6118 			node_dhc->nlp_auth_misc.hrsp_seskey_len = pubkey_len;
6119 		}
6120 
6121 		MD5Update(&mdctx, (unsigned char *)pubkey, pubkey_len);
6122 		MD5Final((uint8_t *)md5_digest, &mdctx);
6123 		bcopy((void *)&md5_digest, (void *)Cai, MD5_LEN);
6124 	}
6125 	if (hash_id == AUTH_SHA1) {
6126 		bzero(&sha1ctx, sizeof (SHA1_CTX));
6127 		SHA1Init(&sha1ctx);
6128 
6129 		SHA1Update(&sha1ctx, (void *)cval, cval_len);
6130 
6131 		err = emlxs_BIGNUM_pubkey(port, pubkey, dhval, dhvallen,
6132 		    key, key_size, dhgp_id, &pubkey_len);
6133 
6134 		if (err != BIG_OK) {
6135 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
6136 			    "hash_Cai: SHA1 BIGNUM_pubkey error: 0x%x",
6137 			    err);
6138 
6139 			err = BIG_GENERAL_ERR;
6140 			return (err);
6141 		}
6142 		if (pubkey_len == 0) {
6143 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
6144 			    "hash_Cai: SA1 BUM_pubkey error: key_len=0");
6145 
6146 			err = BIG_GENERAL_ERR;
6147 			return (err);
6148 		}
6149 		if (ndlp->nlp_DID == FABRIC_DID) {
6150 			bcopy((void *)pubkey,
6151 			    (void *)node_dhc->hrsp_ses_key,
6152 			    pubkey_len);
6153 			node_dhc->hrsp_seskey_len = pubkey_len;
6154 
6155 			/* store extra copy */
6156 			bcopy((void *)pubkey,
6157 			    (void *)node_dhc->nlp_auth_misc.hrsp_ses_key,
6158 			    pubkey_len);
6159 			node_dhc->nlp_auth_misc.hrsp_seskey_len = pubkey_len;
6160 
6161 		} else {
6162 			bcopy((void *)pubkey,
6163 			    (void *)node_dhc->nlp_auth_misc.hrsp_ses_key,
6164 			    pubkey_len);
6165 			node_dhc->nlp_auth_misc.hrsp_seskey_len = pubkey_len;
6166 		}
6167 
6168 		SHA1Update(&sha1ctx, (void *)pubkey, pubkey_len);
6169 		SHA1Final((void *)sha1_digest, &sha1ctx);
6170 		bcopy((void *)&sha1_digest, (void *)Cai, SHA1_LEN);
6171 	}
6172 	return (err);
6173 
6174 } /* emlxs_hash_Cai */
6175 
6176 
6177 /*
6178  * This routine is to verify the DHCHAP_Reply from initiator by the host
6179  * as the responder.
6180  *
6181  * flag: 1: if host is the responder 0: if host is the initiator
6182  *
6183  * if bi_cval != NULL, this routine is used to calculate the response based
6184  * on the challenge from initiator as part of
6185  * DHCHAP_Reply for bi-dirctional authentication.
6186  *
6187  */
6188 /* ARGSUSED */
6189 static uint32_t *
emlxs_hash_verification(emlxs_port_t * port,emlxs_port_dhc_t * port_dhc,NODELIST * ndlp,uint32_t tran_id,uint8_t * dhval,uint32_t dhval_len,uint32_t flag,uint8_t * bi_cval)6190 emlxs_hash_verification(
6191 	emlxs_port_t *port,
6192 	emlxs_port_dhc_t *port_dhc,
6193 	NODELIST *ndlp,
6194 	uint32_t tran_id,
6195 	uint8_t *dhval,
6196 	uint32_t dhval_len,
6197 	uint32_t flag,	/* always 1 for now */
6198 	uint8_t *bi_cval)
6199 {			/* always 0 for now */
6200 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
6201 	uint32_t dhgp_id;
6202 	uint32_t hash_id;
6203 	uint32_t *hash_val = NULL;
6204 	uint32_t hash_size;
6205 	MD5_CTX mdctx;
6206 	SHA1_CTX sha1ctx;
6207 	uint8_t sha1_digest[20];
6208 	uint8_t md5_digest[16];
6209 	uint8_t Cai[20];
6210 	/* union challenge_val un_cval; */
6211 	uint8_t key[20];
6212 	uint8_t cval[20];
6213 	uint32_t cval_len;
6214 	uint8_t mytran_id = 0x00;
6215 	char *remote_key;
6216 	BIG_ERR_CODE err = BIG_OK;
6217 
6218 	tran_id = (AUTH_TRAN_ID_MASK & tran_id);
6219 	mytran_id = (uint8_t)(LE_SWAP32(tran_id));
6220 
6221 	if (ndlp->nlp_DID == FABRIC_DID) {
6222 		remote_key = (char *)node_dhc->auth_key.remote_password;
6223 	} else {
6224 		/*
6225 		 * in case of end-to-end auth, this remote password should be
6226 		 * the password associated with the remote entity. (i.e.,)
6227 		 * for now it is actually local_password.
6228 		 */
6229 		remote_key = (char *)node_dhc->auth_key.remote_password;
6230 	}
6231 
6232 	if (flag == 0) {
6233 		dhgp_id = node_dhc->dhgp_id;
6234 		hash_id = node_dhc->hash_id;
6235 	} else {
6236 		dhgp_id = node_dhc->nlp_auth_dhgpid;
6237 		hash_id = node_dhc->nlp_auth_hashid;
6238 	}
6239 
6240 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
6241 	    "hash_verification: 0x%x 0x%x hash_id=0x%x dhgp_id=0x%x",
6242 	    ndlp->nlp_DID, mytran_id, hash_id, dhgp_id);
6243 
6244 	if (dhval_len == 0) {
6245 		/* NULL DHCHAP group */
6246 		if (hash_id == AUTH_MD5) {
6247 			bzero(&mdctx, sizeof (MD5_CTX));
6248 			hash_size = MD5_LEN;
6249 			MD5Init(&mdctx);
6250 
6251 			MD5Update(&mdctx, (unsigned char *)&mytran_id, 1);
6252 
6253 			if (ndlp->nlp_DID == FABRIC_DID) {
6254 				MD5Update(&mdctx,
6255 				    (unsigned char *)remote_key,
6256 				    node_dhc->auth_key.remote_password_length);
6257 			} else {
6258 				MD5Update(&mdctx,
6259 				    (unsigned char *)remote_key,
6260 				    node_dhc->auth_key.remote_password_length);
6261 			}
6262 
6263 			if (ndlp->nlp_DID == FABRIC_DID) {
6264 				MD5Update(&mdctx,
6265 				    (unsigned char *)&node_dhc->hrsp_cval[0],
6266 				    MD5_LEN);
6267 			} else {
6268 		MD5Update(&mdctx,
6269 		    (unsigned char *)&node_dhc->nlp_auth_misc.hrsp_cval[0],
6270 		    MD5_LEN);
6271 			}
6272 
6273 			MD5Final((uint8_t *)md5_digest, &mdctx);
6274 
6275 			hash_val = (uint32_t *)kmem_alloc(hash_size,
6276 			    KM_NOSLEEP);
6277 			if (hash_val == NULL) {
6278 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
6279 				    "hash_verification: alloc failed");
6280 
6281 				return (NULL);
6282 			} else {
6283 				bcopy((void *)md5_digest,
6284 				    (void *)hash_val, MD5_LEN);
6285 			}
6286 		}
6287 		if (hash_id == AUTH_SHA1) {
6288 			bzero(&sha1ctx, sizeof (SHA1_CTX));
6289 			hash_size = SHA1_LEN;
6290 			SHA1Init(&sha1ctx);
6291 			SHA1Update(&sha1ctx, (void *)&mytran_id, 1);
6292 
6293 			if (ndlp->nlp_DID == FABRIC_DID) {
6294 				SHA1Update(&sha1ctx, (void *)remote_key,
6295 				    node_dhc->auth_key.remote_password_length);
6296 			} else {
6297 				SHA1Update(&sha1ctx, (void *)remote_key,
6298 				    node_dhc->auth_key.remote_password_length);
6299 			}
6300 
6301 			if (ndlp->nlp_DID == FABRIC_DID) {
6302 				SHA1Update(&sha1ctx,
6303 				    (void *)&node_dhc->hrsp_cval[0],
6304 				    SHA1_LEN);
6305 			} else {
6306 			SHA1Update(&sha1ctx,
6307 			    (void *)&node_dhc->nlp_auth_misc.hrsp_cval[0],
6308 			    SHA1_LEN);
6309 			}
6310 
6311 			SHA1Final((void *)sha1_digest, &sha1ctx);
6312 			hash_val = (uint32_t *)kmem_zalloc(hash_size,
6313 			    KM_NOSLEEP);
6314 			if (hash_val == NULL) {
6315 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
6316 				    "hash_verification: alloc failed");
6317 
6318 				return (NULL);
6319 			} else {
6320 				bcopy((void *)sha1_digest,
6321 				    (void *)hash_val, SHA1_LEN);
6322 			}
6323 		}
6324 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
6325 		    "hash_verification: hash_val=0x%x",
6326 		    *(uint32_t *)hash_val);
6327 
6328 		return ((uint32_t *)hash_val);
6329 	} else {
6330 
6331 		/* DHCHAP group 1,2,3,4 */
6332 		/*
6333 		 * host received (g^x mod p) as dhval host has its own
6334 		 * private key y as node_dhc->hrsp_priv_key[] host has its
6335 		 * original challenge c as node_dhc->hrsp_cval[]
6336 		 *
6337 		 * H(c || (g^x mod p)^y mod p) = Cai H(Ti || Km || Cai) =
6338 		 * hash_val returned. Ti : tran_id, Km : shared secret, Cai:
6339 		 * obtained above.
6340 		 */
6341 		if (hash_id == AUTH_MD5) {
6342 			if (ndlp->nlp_DID == FABRIC_DID) {
6343 				bcopy((void *)node_dhc->hrsp_priv_key,
6344 				    (void *)key, MD5_LEN);
6345 			} else {
6346 			bcopy(
6347 			    (void *)node_dhc->nlp_auth_misc.hrsp_priv_key,
6348 			    (void *)key, MD5_LEN);
6349 			}
6350 		}
6351 		if (hash_id == AUTH_SHA1) {
6352 			if (ndlp->nlp_DID == FABRIC_DID) {
6353 				bcopy((void *)node_dhc->hrsp_priv_key,
6354 				    (void *)key, SHA1_LEN);
6355 			} else {
6356 			bcopy(
6357 			    (void *)node_dhc->nlp_auth_misc.hrsp_priv_key,
6358 			    (void *)key, SHA1_LEN);
6359 			}
6360 		}
6361 		if (ndlp->nlp_DID == FABRIC_DID) {
6362 			bcopy((void *)node_dhc->hrsp_cval,
6363 			    (void *)cval, node_dhc->hrsp_cval_len);
6364 			cval_len = node_dhc->hrsp_cval_len;
6365 		} else {
6366 			bcopy((void *)node_dhc->nlp_auth_misc.hrsp_cval,
6367 			    (void *)cval,
6368 			    node_dhc->nlp_auth_misc.hrsp_cval_len);
6369 			cval_len = node_dhc->nlp_auth_misc.hrsp_cval_len;
6370 		}
6371 
6372 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
6373 		    "hash_verification: N-Null gp. 0x%x 0x%x",
6374 		    ndlp->nlp_DID, cval_len);
6375 
6376 		err = emlxs_hash_Cai(port, port_dhc, ndlp, (void *)Cai,
6377 		    hash_id, dhgp_id,
6378 		    tran_id, cval, cval_len,
6379 		    key, dhval, dhval_len);
6380 
6381 		if (err != BIG_OK) {
6382 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
6383 			    "hash_verification: Cai error. ret=0x%x",
6384 			    err);
6385 
6386 			return (NULL);
6387 		}
6388 		if (hash_id == AUTH_MD5) {
6389 			bzero(&mdctx, sizeof (MD5_CTX));
6390 			hash_size = MD5_LEN;
6391 
6392 			MD5Init(&mdctx);
6393 			MD5Update(&mdctx, (unsigned char *)&mytran_id, 1);
6394 
6395 			if (ndlp->nlp_DID == FABRIC_DID) {
6396 				MD5Update(&mdctx,
6397 				    (unsigned char *)remote_key,
6398 				    node_dhc->auth_key.remote_password_length);
6399 			} else {
6400 				MD5Update(&mdctx,
6401 				    (unsigned char *)remote_key,
6402 				    node_dhc->auth_key.remote_password_length);
6403 			}
6404 
6405 			MD5Update(&mdctx, (unsigned char *)Cai, MD5_LEN);
6406 			MD5Final((uint8_t *)md5_digest, &mdctx);
6407 
6408 			hash_val = (uint32_t *)kmem_zalloc(hash_size,
6409 			    KM_NOSLEEP);
6410 			if (hash_val == NULL) {
6411 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
6412 				    "hash_vf: alloc failed(Non-NULL dh)");
6413 
6414 				return (NULL);
6415 			} else {
6416 				bcopy((void *)&md5_digest,
6417 				    (void *)hash_val, MD5_LEN);
6418 			}
6419 		}
6420 		if (hash_id == AUTH_SHA1) {
6421 			bzero(&sha1ctx, sizeof (SHA1_CTX));
6422 			hash_size = SHA1_LEN;
6423 
6424 			SHA1Init(&sha1ctx);
6425 			SHA1Update(&sha1ctx, (void *)&mytran_id, 1);
6426 
6427 			if (ndlp->nlp_DID == FABRIC_DID) {
6428 				SHA1Update(&sha1ctx, (void *)remote_key,
6429 				    node_dhc->auth_key.remote_password_length);
6430 			} else {
6431 				SHA1Update(&sha1ctx, (void *)remote_key,
6432 				    node_dhc->auth_key.remote_password_length);
6433 			}
6434 
6435 			SHA1Update(&sha1ctx, (void *)Cai, SHA1_LEN);
6436 			SHA1Final((void *)sha1_digest, &sha1ctx);
6437 
6438 			hash_val = (uint32_t *)kmem_zalloc(hash_size,
6439 			    KM_NOSLEEP);
6440 			if (hash_val == NULL) {
6441 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
6442 			    "hash_vf: val alloc failed (Non-NULL dh)");
6443 
6444 				return (NULL);
6445 			} else {
6446 				bcopy((void *)&sha1_digest,
6447 				    (void *)hash_val, SHA1_LEN);
6448 			}
6449 		}
6450 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
6451 		    "hash_verification: hash_val=0x%x",
6452 		    *(uint32_t *)hash_val);
6453 
6454 		return ((uint32_t *)hash_val);
6455 	}
6456 
6457 } /* emlxs_hash_verification */
6458 
6459 
6460 
6461 /*
6462  * When DHCHAP_Success msg was sent from responder to the initiator,
6463  * with bi-directional authentication requested, the
6464  * DHCHAP_Success contains the response R2 to the challenge C2 received.
6465  *
6466  * DHCHAP response R2: The value of R2 is computed using the hash function
6467  * H() selected by the HashID parameter of the
6468  * DHCHAP_Challenge msg, and the augmented challenge Ca2.
6469  *
6470  * NULL DH group: Ca2 = C2 Non NULL DH group: Ca2 = H(C2 ||
6471  * (g^y mod p)^x mod p)) x is selected by the authentication responder
6472  * which is the node_dhc->hrsp_priv_key[] (g^y mod p) is dhval received
6473  * from authentication initiator.
6474  *
6475  * R2 = H(Ti || Km || Ca2) Ti is the least significant byte of the
6476  * transaction id. Km is the secret associated with the
6477  * authentication responder.
6478  *
6479  * emlxs_hash_get_R2 and emlxs_hash_verification could be mergerd into one
6480  * function later.
6481  *
6482  */
6483 static uint32_t *
emlxs_hash_get_R2(emlxs_port_t * port,emlxs_port_dhc_t * port_dhc,NODELIST * ndlp,uint32_t tran_id,uint8_t * dhval,uint32_t dhval_len,uint32_t flag,uint8_t * bi_cval)6484 emlxs_hash_get_R2(
6485 	emlxs_port_t *port,
6486 	emlxs_port_dhc_t *port_dhc,
6487 	NODELIST *ndlp,
6488 	uint32_t tran_id,
6489 	uint8_t *dhval,
6490 	uint32_t dhval_len,
6491 	uint32_t flag,	/* flag 1 rsponder or 0 initiator */
6492 	uint8_t *bi_cval)
6493 {
6494 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
6495 
6496 	uint32_t dhgp_id;
6497 	uint32_t hash_id;
6498 	uint32_t *hash_val = NULL;
6499 	uint32_t hash_size;
6500 	MD5_CTX mdctx;
6501 	SHA1_CTX sha1ctx;
6502 	uint8_t sha1_digest[20];
6503 	uint8_t md5_digest[16];
6504 	uint8_t Cai[20];
6505 	/* union challenge_val un_cval; */
6506 	uint8_t key[20];
6507 	uint32_t cval_len;
6508 	uint8_t mytran_id = 0x00;
6509 
6510 	char *mykey;
6511 	BIG_ERR_CODE err = BIG_OK;
6512 
6513 	if (ndlp->nlp_DID == FABRIC_DID) {
6514 		dhgp_id = node_dhc->nlp_auth_dhgpid;
6515 		hash_id = node_dhc->nlp_auth_hashid;
6516 	} else {
6517 		if (flag == 0) {
6518 			dhgp_id = node_dhc->dhgp_id;
6519 			hash_id = node_dhc->hash_id;
6520 		} else {
6521 			dhgp_id = node_dhc->nlp_auth_dhgpid;
6522 			hash_id = node_dhc->nlp_auth_hashid;
6523 		}
6524 	}
6525 
6526 	tran_id = (AUTH_TRAN_ID_MASK & tran_id);
6527 	mytran_id = (uint8_t)(LE_SWAP32(tran_id));
6528 
6529 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
6530 	    "hash_get_R2:0x%x 0x%x dhgp_id=0x%x mytran_id=0x%x",
6531 	    ndlp->nlp_DID, hash_id, dhgp_id, mytran_id);
6532 
6533 	if (ndlp->nlp_DID == FABRIC_DID) {
6534 		mykey = (char *)node_dhc->auth_key.local_password;
6535 
6536 	} else {
6537 		/* in case of end-to-end mykey should be remote_password */
6538 		mykey = (char *)node_dhc->auth_key.remote_password;
6539 	}
6540 
6541 	if (dhval_len == 0) {
6542 		/* NULL DHCHAP group */
6543 		if (hash_id == AUTH_MD5) {
6544 			bzero(&mdctx, sizeof (MD5_CTX));
6545 			hash_size = MD5_LEN;
6546 			MD5Init(&mdctx);
6547 
6548 			MD5Update(&mdctx, (unsigned char *)&mytran_id, 1);
6549 
6550 			if (ndlp->nlp_DID == FABRIC_DID) {
6551 				MD5Update(&mdctx, (unsigned char *)mykey,
6552 				    node_dhc->auth_key.local_password_length);
6553 			} else {
6554 				MD5Update(&mdctx, (unsigned char *)mykey,
6555 				    node_dhc->auth_key.remote_password_length);
6556 			}
6557 
6558 			MD5Update(&mdctx, (unsigned char *)bi_cval, MD5_LEN);
6559 
6560 			MD5Final((uint8_t *)md5_digest, &mdctx);
6561 
6562 			hash_val = (uint32_t *)kmem_alloc(hash_size,
6563 			    KM_NOSLEEP);
6564 			if (hash_val == NULL) {
6565 				return (NULL);
6566 			} else {
6567 				bcopy((void *)md5_digest,
6568 				    (void *)hash_val, MD5_LEN);
6569 			}
6570 		}
6571 		if (hash_id == AUTH_SHA1) {
6572 			bzero(&sha1ctx, sizeof (SHA1_CTX));
6573 			hash_size = SHA1_LEN;
6574 			SHA1Init(&sha1ctx);
6575 			SHA1Update(&sha1ctx, (void *)&mytran_id, 1);
6576 
6577 			if (ndlp->nlp_DID == FABRIC_DID) {
6578 				SHA1Update(&sha1ctx, (void *)mykey,
6579 				    node_dhc->auth_key.local_password_length);
6580 			} else {
6581 				SHA1Update(&sha1ctx, (void *)mykey,
6582 				    node_dhc->auth_key.remote_password_length);
6583 			}
6584 
6585 			SHA1Update(&sha1ctx, (void *)bi_cval, SHA1_LEN);
6586 			SHA1Final((void *)sha1_digest, &sha1ctx);
6587 			hash_val = (uint32_t *)kmem_alloc(hash_size,
6588 			    KM_NOSLEEP);
6589 			if (hash_val == NULL) {
6590 				return (NULL);
6591 			} else {
6592 				bcopy((void *)sha1_digest,
6593 				    (void *)hash_val, SHA1_LEN);
6594 			}
6595 		}
6596 	} else {
6597 		/* NON-NULL DHCHAP */
6598 		if (ndlp->nlp_DID == FABRIC_DID) {
6599 			if (hash_id == AUTH_MD5) {
6600 				bcopy((void *)node_dhc->hrsp_priv_key,
6601 				    (void *)key, MD5_LEN);
6602 			}
6603 			if (hash_id == AUTH_SHA1) {
6604 				bcopy((void *)node_dhc->hrsp_priv_key,
6605 				    (void *)key, SHA1_LEN);
6606 			}
6607 			cval_len = node_dhc->hrsp_cval_len;
6608 		} else {
6609 			if (hash_id == AUTH_MD5) {
6610 			bcopy(
6611 			    (void *)node_dhc->nlp_auth_misc.hrsp_priv_key,
6612 			    (void *)key, MD5_LEN);
6613 			}
6614 			if (hash_id == AUTH_SHA1) {
6615 			bcopy(
6616 			    (void *)node_dhc->nlp_auth_misc.hrsp_priv_key,
6617 			    (void *)key, SHA1_LEN);
6618 			}
6619 			cval_len = node_dhc->nlp_auth_misc.hrsp_cval_len;
6620 		}
6621 
6622 		/* use bi_cval here */
6623 		/*
6624 		 * key: x dhval: (g^y mod p) tran_id: Ti bi_cval: C2 hash_id:
6625 		 * H dhgp_id: p/g
6626 		 *
6627 		 * Cai = H (C2 || ((g^y mod p)^x mod p) )
6628 		 *
6629 		 * R2 = H (Ti || Km || Cai)
6630 		 */
6631 		err = emlxs_hash_Cai(port, port_dhc, ndlp, (void *)Cai,
6632 		    hash_id, dhgp_id, tran_id, bi_cval, cval_len,
6633 		    key, dhval, dhval_len);
6634 
6635 		if (err != BIG_OK) {
6636 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
6637 			    "hash_get_R2: hash_Cai error. ret=0x%x",
6638 			    err);
6639 
6640 			return (NULL);
6641 		}
6642 		if (hash_id == AUTH_MD5) {
6643 			bzero(&mdctx, sizeof (MD5_CTX));
6644 			hash_size = MD5_LEN;
6645 
6646 			MD5Init(&mdctx);
6647 			MD5Update(&mdctx, (unsigned char *) &mytran_id, 1);
6648 
6649 			/*
6650 			 * Here we use the same key: mykey, note: this mykey
6651 			 * should be the key associated with the
6652 			 * authentication responder i.e. the remote key.
6653 			 */
6654 			if (ndlp->nlp_DID == FABRIC_DID)
6655 				MD5Update(&mdctx, (unsigned char *)mykey,
6656 				    node_dhc->auth_key.local_password_length);
6657 			else
6658 				MD5Update(&mdctx, (unsigned char *)mykey,
6659 				    node_dhc->auth_key.remote_password_length);
6660 
6661 			MD5Update(&mdctx, (unsigned char *)Cai, MD5_LEN);
6662 			MD5Final((uint8_t *)md5_digest, &mdctx);
6663 
6664 			hash_val = (uint32_t *)kmem_alloc(hash_size,
6665 			    KM_NOSLEEP);
6666 			if (hash_val == NULL) {
6667 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
6668 			    "hash_get_R2: hash_val MD5 alloc failed.");
6669 
6670 				return (NULL);
6671 			} else {
6672 				bcopy((void *)md5_digest,
6673 				    (void *)hash_val, MD5_LEN);
6674 			}
6675 		}
6676 		if (hash_id == AUTH_SHA1) {
6677 			bzero(&sha1ctx, sizeof (SHA1_CTX));
6678 			hash_size = SHA1_LEN;
6679 
6680 			SHA1Init(&sha1ctx);
6681 			SHA1Update(&sha1ctx, (void *)&mytran_id, 1);
6682 
6683 			if (ndlp->nlp_DID == FABRIC_DID) {
6684 				SHA1Update(&sha1ctx, (void *)mykey,
6685 				    node_dhc->auth_key.local_password_length);
6686 			} else {
6687 				SHA1Update(&sha1ctx, (void *)mykey,
6688 				    node_dhc->auth_key.remote_password_length);
6689 			}
6690 
6691 			SHA1Update(&sha1ctx, (void *)Cai, SHA1_LEN);
6692 			SHA1Final((void *)sha1_digest, &sha1ctx);
6693 
6694 			hash_val = (uint32_t *)kmem_alloc(hash_size,
6695 			    KM_NOSLEEP);
6696 			if (hash_val == NULL) {
6697 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
6698 			    "hash_get_R2: hash_val SHA1 alloc failed.");
6699 
6700 				return (NULL);
6701 			} else {
6702 				bcopy((void *)sha1_digest,
6703 				    (void *)hash_val, SHA1_LEN);
6704 			}
6705 		}
6706 	}
6707 
6708 	return ((uint32_t *)hash_val);
6709 
6710 } /* emlxs_hash_get_R2 */
6711 
6712 
6713 static void
emlxs_log_auth_event(emlxs_port_t * port,NODELIST * ndlp,char * subclass,char * info)6714 emlxs_log_auth_event(
6715 	emlxs_port_t *port,
6716 	NODELIST *ndlp,
6717 	char *subclass,
6718 	char *info)
6719 {
6720 	emlxs_hba_t *hba = HBA;
6721 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
6722 	nvlist_t *attr_list = NULL;
6723 	dev_info_t *dip = hba->dip;
6724 	emlxs_auth_cfg_t *auth_cfg;
6725 	char *tmp = "No_more_logging_information_available";
6726 	uint8_t lwwn[8];
6727 	uint8_t rwwn[8];
6728 	char *lwwn_str = NULL;
6729 	char *rwwn_str = NULL;
6730 	char ext_subclass[128];
6731 	char ext_class[32];
6732 
6733 	auth_cfg = &(node_dhc->auth_cfg);
6734 
6735 	if (info == NULL) {
6736 		info = tmp;
6737 	}
6738 	bcopy((void *) &auth_cfg->local_entity, (void *)lwwn, 8);
6739 	lwwn_str = (char *)kmem_zalloc(32, KM_NOSLEEP);
6740 	if (lwwn_str == NULL) {
6741 		return;
6742 	}
6743 	(void) snprintf(lwwn_str, 32, "%02X%02X%02X%02X%02X%02X%02X%02X",
6744 	    lwwn[0], lwwn[1], lwwn[2], lwwn[3], lwwn[4], lwwn[5], lwwn[6],
6745 	    lwwn[7]);
6746 
6747 	bcopy((void *)&auth_cfg->remote_entity, (void *)rwwn, 8);
6748 	rwwn_str = (char *)kmem_zalloc(32, KM_NOSLEEP);
6749 	if (rwwn_str == NULL) {
6750 		kmem_free(lwwn_str, 32);
6751 		return;
6752 	}
6753 
6754 	(void) snprintf(rwwn_str, 32, "%02X%02X%02X%02X%02X%02X%02X%02X",
6755 	    rwwn[0], rwwn[1], rwwn[2], rwwn[3], rwwn[4], rwwn[5], rwwn[6],
6756 	    rwwn[7]);
6757 
6758 	(void) snprintf(ext_subclass, sizeof (ext_subclass),
6759 	    "ESC_%s_%s", DRIVER_NAME, subclass);
6760 	(void) snprintf(ext_class, sizeof (ext_class),
6761 	    "EC_%s", DRIVER_NAME);
6762 
6763 	if (nvlist_alloc(&attr_list, NV_UNIQUE_NAME_TYPE, KM_NOSLEEP)
6764 	    == DDI_SUCCESS) {
6765 		if ((nvlist_add_uint32(attr_list, "instance",
6766 		    ddi_get_instance(dip)) == DDI_SUCCESS) &&
6767 		    (nvlist_add_string(attr_list, "lwwn",
6768 		    lwwn_str) == DDI_SUCCESS) &&
6769 		    (nvlist_add_string(attr_list, "rwwn",
6770 		    rwwn_str) == DDI_SUCCESS) &&
6771 		    (nvlist_add_string(attr_list, "Info",
6772 		    info) == DDI_SUCCESS) &&
6773 		    (nvlist_add_string(attr_list, "Class",
6774 		    ext_class) == DDI_SUCCESS) &&
6775 		    (nvlist_add_string(attr_list, "SubClass",
6776 		    ext_subclass) == DDI_SUCCESS)) {
6777 
6778 			(void) ddi_log_sysevent(dip,
6779 			    emlxs_strtoupper(DRIVER_NAME),
6780 			    ext_class,
6781 			    ext_subclass,
6782 			    attr_list,
6783 			    NULL,
6784 			    DDI_NOSLEEP);
6785 		}
6786 		nvlist_free(attr_list);
6787 		attr_list = NULL;
6788 	}
6789 	kmem_free(lwwn_str, 32);
6790 	kmem_free(rwwn_str, 32);
6791 
6792 	return;
6793 
6794 } /* emlxs_log_auth_event() */
6795 
6796 
6797 /* **************************** AUTH DHC INTERFACE ************************* */
6798 
6799 extern int
emlxs_dhc_auth_start(emlxs_port_t * port,emlxs_node_t * ndlp,uint8_t * deferred_sbp,uint8_t * deferred_ubp)6800 emlxs_dhc_auth_start(
6801 	emlxs_port_t *port,
6802 	emlxs_node_t *ndlp,
6803 	uint8_t *deferred_sbp,
6804 	uint8_t *deferred_ubp)
6805 {
6806 	emlxs_hba_t *hba = HBA;
6807 	emlxs_config_t *cfg = &CFG;
6808 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
6809 	emlxs_auth_cfg_t *auth_cfg;
6810 	emlxs_auth_key_t *auth_key;
6811 	uint32_t i;
6812 	uint32_t fabric;
6813 	uint32_t fabric_switch;
6814 
6815 	/* The ubp represents an unsolicted PLOGI */
6816 	/* The sbp represents a solicted PLOGI    */
6817 
6818 	fabric = ((ndlp->nlp_DID & FABRIC_DID_MASK) == FABRIC_DID_MASK) ? 1 : 0;
6819 	fabric_switch = ((ndlp->nlp_DID == FABRIC_DID) ? 1 : 0);
6820 
6821 	/* Return is authentication is not enabled */
6822 	if (cfg[CFG_AUTH_ENABLE].current == 0) {
6823 		EMLXS_MSGF(EMLXS_CONTEXT,
6824 		    &emlxs_fcsp_start_msg,
6825 		    "Not started. Auth disabled. did=0x%x", ndlp->nlp_DID);
6826 
6827 		emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_DISABLED, 0, 0);
6828 
6829 		return (1);
6830 	}
6831 	if (port->vpi != 0 && cfg[CFG_AUTH_NPIV].current == 0) {
6832 		EMLXS_MSGF(EMLXS_CONTEXT,
6833 		    &emlxs_fcsp_start_msg,
6834 		    "Not started. NPIV auth disabled. did=0x%x", ndlp->nlp_DID);
6835 
6836 		emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_DISABLED, 0, 0);
6837 
6838 		return (1);
6839 	}
6840 	if (!fabric_switch && fabric) {
6841 		EMLXS_MSGF(EMLXS_CONTEXT,
6842 		    &emlxs_fcsp_start_msg,
6843 		    "Not started. FS auth disabled. did=0x%x", ndlp->nlp_DID);
6844 
6845 		emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_DISABLED, 0, 0);
6846 
6847 		return (1);
6848 	}
6849 	/* Return if fcsp support to this node is not enabled */
6850 	if (!fabric_switch && cfg[CFG_AUTH_E2E].current == 0) {
6851 		EMLXS_MSGF(EMLXS_CONTEXT,
6852 		    &emlxs_fcsp_start_msg,
6853 		    "Not started. E2E auth disabled. did=0x%x", ndlp->nlp_DID);
6854 
6855 		emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_DISABLED, 0, 0);
6856 
6857 		return (1);
6858 	}
6859 	if ((deferred_sbp && node_dhc->deferred_sbp) ||
6860 	    (deferred_ubp && node_dhc->deferred_ubp)) {
6861 		/* Clear previous authentication */
6862 		emlxs_dhc_auth_stop(port, ndlp);
6863 	}
6864 	mutex_enter(&hba->auth_lock);
6865 
6866 	/* Intialize node */
6867 	node_dhc->parent_auth_cfg = NULL;
6868 	node_dhc->parent_auth_key = NULL;
6869 
6870 	/* Acquire auth configuration */
6871 	if (fabric_switch) {
6872 		auth_cfg = emlxs_auth_cfg_find(port,
6873 		    (uint8_t *)emlxs_fabric_wwn);
6874 		auth_key = emlxs_auth_key_find(port,
6875 		    (uint8_t *)emlxs_fabric_wwn);
6876 	} else {
6877 		auth_cfg = emlxs_auth_cfg_find(port,
6878 		    (uint8_t *)&ndlp->nlp_portname);
6879 		auth_key = emlxs_auth_key_find(port,
6880 		    (uint8_t *)&ndlp->nlp_portname);
6881 	}
6882 
6883 	if (!auth_cfg) {
6884 		mutex_exit(&hba->auth_lock);
6885 
6886 		EMLXS_MSGF(EMLXS_CONTEXT,
6887 		    &emlxs_fcsp_start_msg,
6888 		    "Not started. No auth cfg entry found. did=0x%x",
6889 		    ndlp->nlp_DID);
6890 
6891 		emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_DISABLED, 0, 0);
6892 
6893 		return (1);
6894 	}
6895 	if (fabric_switch) {
6896 		auth_cfg->node = NULL;
6897 	} else {
6898 		node_dhc->parent_auth_cfg = auth_cfg;
6899 		auth_cfg->node = ndlp;
6900 	}
6901 
6902 	if (!auth_key) {
6903 		mutex_exit(&hba->auth_lock);
6904 
6905 		EMLXS_MSGF(EMLXS_CONTEXT,
6906 		    &emlxs_fcsp_start_msg,
6907 		    "Not started. No auth key entry found. did=0x%x",
6908 		    ndlp->nlp_DID);
6909 
6910 		emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_DISABLED, 0, 0);
6911 
6912 		return (1);
6913 	}
6914 	if (fabric_switch) {
6915 		auth_key->node = NULL;
6916 	} else {
6917 		node_dhc->parent_auth_key = auth_key;
6918 		auth_key->node = ndlp;
6919 	}
6920 
6921 	/* Remote port does not support fcsp */
6922 	if (ndlp->sparm.cmn.fcsp_support == 0) {
6923 		switch (auth_cfg->authentication_mode) {
6924 		case AUTH_MODE_PASSIVE:
6925 			mutex_exit(&hba->auth_lock);
6926 
6927 			EMLXS_MSGF(EMLXS_CONTEXT,
6928 			    &emlxs_fcsp_start_msg,
6929 			    "Not started. Auth unsupported. did=0x%x",
6930 			    ndlp->nlp_DID);
6931 
6932 			emlxs_dhc_state(port, ndlp,
6933 			    NODE_STATE_AUTH_DISABLED, 0, 0);
6934 			return (1);
6935 
6936 		case AUTH_MODE_ACTIVE:
6937 			mutex_exit(&hba->auth_lock);
6938 
6939 			EMLXS_MSGF(EMLXS_CONTEXT,
6940 			    &emlxs_fcsp_start_msg,
6941 			    "Failed. Auth unsupported. did=0x%x",
6942 			    ndlp->nlp_DID);
6943 
6944 			/*
6945 			 * Save packet for deferred completion until
6946 			 * authentication is complete
6947 			 */
6948 			ndlp->node_dhc.deferred_sbp = deferred_sbp;
6949 			ndlp->node_dhc.deferred_ubp = deferred_ubp;
6950 
6951 			goto failed;
6952 
6953 		case AUTH_MODE_DISABLED:
6954 		default:
6955 			mutex_exit(&hba->auth_lock);
6956 
6957 			EMLXS_MSGF(EMLXS_CONTEXT,
6958 			    &emlxs_fcsp_start_msg,
6959 			    "Not started. Auth mode=disabled. did=0x%x",
6960 			    ndlp->nlp_DID);
6961 
6962 			emlxs_dhc_state(port, ndlp,
6963 			    NODE_STATE_AUTH_DISABLED, 0, 0);
6964 			return (1);
6965 		}
6966 	} else {	/* Remote port supports fcsp */
6967 		switch (auth_cfg->authentication_mode) {
6968 		case AUTH_MODE_PASSIVE:
6969 		case AUTH_MODE_ACTIVE:
6970 			/* start auth */
6971 			break;
6972 
6973 		case AUTH_MODE_DISABLED:
6974 		default:
6975 			mutex_exit(&hba->auth_lock);
6976 
6977 			EMLXS_MSGF(EMLXS_CONTEXT,
6978 			    &emlxs_fcsp_start_msg,
6979 			    "Failed. Auth mode=disabled. did=0x%x",
6980 			    ndlp->nlp_DID);
6981 
6982 			/*
6983 			 * Save packet for deferred completion until
6984 			 * authentication is complete
6985 			 */
6986 			ndlp->node_dhc.deferred_sbp = deferred_sbp;
6987 			ndlp->node_dhc.deferred_ubp = deferred_ubp;
6988 
6989 			goto failed;
6990 		}
6991 	}
6992 
6993 	/* We have a GO for authentication */
6994 
6995 	/*
6996 	 * Save pointers for deferred completion until authentication is
6997 	 * complete
6998 	 */
6999 	node_dhc->deferred_sbp = deferred_sbp;
7000 	node_dhc->deferred_ubp = deferred_ubp;
7001 
7002 	bzero(&node_dhc->auth_cfg, sizeof (node_dhc->auth_cfg));
7003 	bzero(&node_dhc->auth_key, sizeof (node_dhc->auth_key));
7004 
7005 	/* Program node's auth cfg */
7006 	bcopy((uint8_t *)&port->wwpn,
7007 	    (uint8_t *)&node_dhc->auth_cfg.local_entity, 8);
7008 	bcopy((uint8_t *)&ndlp->nlp_portname,
7009 	    (uint8_t *)&node_dhc->auth_cfg.remote_entity, 8);
7010 
7011 	node_dhc->auth_cfg.authentication_timeout =
7012 	    auth_cfg->authentication_timeout;
7013 	node_dhc->auth_cfg.authentication_mode =
7014 	    auth_cfg->authentication_mode;
7015 
7016 	/*
7017 	 * If remote password type is "ignore", then only unidirectional auth
7018 	 * is allowed
7019 	 */
7020 	if (auth_key->remote_password_type == 3) {
7021 		node_dhc->auth_cfg.bidirectional = 0;
7022 	} else {
7023 		node_dhc->auth_cfg.bidirectional = auth_cfg->bidirectional;
7024 	}
7025 
7026 	node_dhc->auth_cfg.reauthenticate_time_interval =
7027 	    auth_cfg->reauthenticate_time_interval;
7028 
7029 	for (i = 0; i < 4; i++) {
7030 		switch (auth_cfg->authentication_type_priority[i]) {
7031 		case ELX_DHCHAP:
7032 			node_dhc->auth_cfg.authentication_type_priority[i] =
7033 			    AUTH_DHCHAP;
7034 			break;
7035 
7036 		case ELX_FCAP:
7037 			node_dhc->auth_cfg.authentication_type_priority[i] =
7038 			    AUTH_FCAP;
7039 			break;
7040 
7041 		case ELX_FCPAP:
7042 			node_dhc->auth_cfg.authentication_type_priority[i] =
7043 			    AUTH_FCPAP;
7044 			break;
7045 
7046 		case ELX_KERBEROS:
7047 			node_dhc->auth_cfg.authentication_type_priority[i] =
7048 			    AUTH_KERBEROS;
7049 			break;
7050 
7051 		default:
7052 			node_dhc->auth_cfg.authentication_type_priority[i] =
7053 			    0;
7054 			break;
7055 		}
7056 
7057 		switch (auth_cfg->hash_priority[i]) {
7058 		case ELX_SHA1:
7059 			node_dhc->auth_cfg.hash_priority[i] = AUTH_SHA1;
7060 			break;
7061 
7062 		case ELX_MD5:
7063 			node_dhc->auth_cfg.hash_priority[i] = AUTH_MD5;
7064 			break;
7065 
7066 		default:
7067 			node_dhc->auth_cfg.hash_priority[i] = 0;
7068 			break;
7069 		}
7070 	}
7071 
7072 	for (i = 0; i < 8; i++) {
7073 		switch (auth_cfg->dh_group_priority[i]) {
7074 		case ELX_GROUP_NULL:
7075 			node_dhc->auth_cfg.dh_group_priority[i] = GROUP_NULL;
7076 			break;
7077 
7078 		case ELX_GROUP_1024:
7079 			node_dhc->auth_cfg.dh_group_priority[i] = GROUP_1024;
7080 			break;
7081 
7082 		case ELX_GROUP_1280:
7083 			node_dhc->auth_cfg.dh_group_priority[i] = GROUP_1280;
7084 			break;
7085 
7086 		case ELX_GROUP_1536:
7087 			node_dhc->auth_cfg.dh_group_priority[i] = GROUP_1536;
7088 			break;
7089 
7090 		case ELX_GROUP_2048:
7091 			node_dhc->auth_cfg.dh_group_priority[i] = GROUP_2048;
7092 			break;
7093 
7094 		default:
7095 			node_dhc->auth_cfg.dh_group_priority[i] = 0xF;
7096 			break;
7097 		}
7098 	}
7099 
7100 	/* Program the node's key */
7101 	if (auth_key) {
7102 		bcopy((uint8_t *)auth_key,
7103 		    (uint8_t *)&node_dhc->auth_key,
7104 		    sizeof (emlxs_auth_key_t));
7105 		node_dhc->auth_key.next = NULL;
7106 		node_dhc->auth_key.prev = NULL;
7107 
7108 		bcopy((uint8_t *)&port->wwpn,
7109 		    (uint8_t *)&node_dhc->auth_key.local_entity, 8);
7110 		bcopy((uint8_t *)&ndlp->nlp_portname,
7111 		    (uint8_t *)&node_dhc->auth_key.remote_entity,
7112 		    8);
7113 	}
7114 	mutex_exit(&hba->auth_lock);
7115 
7116 	node_dhc->nlp_auth_limit = 2;
7117 	node_dhc->nlp_fb_vendor = 1;
7118 
7119 	node_dhc->nlp_authrsp_tmocnt = 0;
7120 	node_dhc->nlp_authrsp_tmo = 0;
7121 
7122 	if (deferred_ubp) {
7123 		/* Acknowledge the unsolicited PLOGI */
7124 		/* This should trigger the other port to start authentication */
7125 		if (emlxs_ub_send_login_acc(port,
7126 		    (fc_unsol_buf_t *)deferred_ubp) != FC_SUCCESS) {
7127 			EMLXS_MSGF(EMLXS_CONTEXT,
7128 			    &emlxs_fcsp_start_msg,
7129 			    "Not started. Unable to send PLOGI ACC. did=0x%x",
7130 			    ndlp->nlp_DID);
7131 
7132 			goto failed;
7133 		}
7134 		/* Start the auth rsp timer */
7135 		node_dhc->nlp_authrsp_tmo = DRV_TIME +
7136 		    node_dhc->auth_cfg.authentication_timeout;
7137 
7138 		EMLXS_MSGF(EMLXS_CONTEXT,
7139 		    &emlxs_fcsp_start_msg,
7140 		    "Authrsp timer activated. did=0x%x",
7141 		    ndlp->nlp_DID);
7142 
7143 		/* The next state should be emlxs_rcv_auth_msg_unmapped_node */
7144 		emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_SUCCESS, 0, 0);
7145 	} else {
7146 		node_dhc->nlp_auth_flag = 1;	/* host is the initiator */
7147 
7148 		EMLXS_MSGF(EMLXS_CONTEXT,
7149 		    &emlxs_fcsp_start_msg,
7150 		    "Auth initiated. did=0x%x limit=%d sbp=%p",
7151 		    ndlp->nlp_DID, node_dhc->nlp_auth_limit, deferred_sbp);
7152 
7153 		if (emlxs_issue_auth_negotiate(port, ndlp, 0)) {
7154 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_start_msg,
7155 			    "Failed. Auth initiation failed. did=0x%x",
7156 			    ndlp->nlp_DID);
7157 
7158 			goto failed;
7159 		}
7160 	}
7161 
7162 	return (0);
7163 
7164 failed:
7165 
7166 	emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_FAILED, 0, 0);
7167 
7168 	/* Complete authentication with failed status */
7169 	emlxs_dhc_auth_complete(port, ndlp, 1);
7170 
7171 	return (0);
7172 
7173 } /* emlxs_dhc_auth_start() */
7174 
7175 
7176 
7177 /* This is called to indicate the driver has lost connection with this node */
7178 extern void
emlxs_dhc_auth_stop(emlxs_port_t * port,emlxs_node_t * ndlp)7179 emlxs_dhc_auth_stop(
7180 	emlxs_port_t *port,
7181 	emlxs_node_t *ndlp)
7182 {
7183 	emlxs_port_dhc_t *port_dhc = &port->port_dhc;
7184 	emlxs_node_dhc_t *node_dhc;
7185 	uint32_t i;
7186 
7187 	if (port_dhc->state == ELX_FABRIC_STATE_UNKNOWN) {
7188 		/* Nothing to stop */
7189 		return;
7190 	}
7191 	if (ndlp) {
7192 		node_dhc = &ndlp->node_dhc;
7193 
7194 		if (node_dhc->state == NODE_STATE_UNKNOWN) {
7195 			/* Nothing to stop */
7196 			return;
7197 		}
7198 		if (ndlp->nlp_DID != FABRIC_DID) {
7199 			emlxs_dhc_state(port, ndlp, NODE_STATE_UNKNOWN, 0, 0);
7200 		}
7201 		emlxs_dhc_auth_complete(port, ndlp, 2);
7202 	} else {	/* Lost connection to all nodes for this port */
7203 		rw_enter(&port->node_rwlock, RW_READER);
7204 		for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
7205 			ndlp = port->node_table[i];
7206 
7207 			if (!ndlp) {
7208 				continue;
7209 			}
7210 			node_dhc = &ndlp->node_dhc;
7211 
7212 			if (node_dhc->state == NODE_STATE_UNKNOWN) {
7213 				continue;
7214 			}
7215 			if (ndlp->nlp_DID != FABRIC_DID) {
7216 				emlxs_dhc_state(port, ndlp,
7217 				    NODE_STATE_UNKNOWN, 0, 0);
7218 			}
7219 			emlxs_dhc_auth_complete(port, ndlp, 2);
7220 		}
7221 		rw_exit(&port->node_rwlock);
7222 	}
7223 
7224 	return;
7225 
7226 } /* emlxs_dhc_auth_stop */
7227 
7228 
7229 /* state = 0   - Successful completion. Continue connection to node */
7230 /* state = 1   - Failed completion. Do not continue with connection to node */
7231 /* state = 2   - Stopped completion. Do not continue with connection to node */
7232 
7233 static void
emlxs_dhc_auth_complete(emlxs_port_t * port,emlxs_node_t * ndlp,uint32_t status)7234 emlxs_dhc_auth_complete(
7235 			emlxs_port_t *port,
7236 			emlxs_node_t *ndlp,
7237 			uint32_t status)
7238 {
7239 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
7240 	uint32_t fabric;
7241 	uint32_t fabric_switch;
7242 
7243 	fabric = ((ndlp->nlp_DID & FABRIC_DID_MASK) == FABRIC_DID_MASK) ? 1 : 0;
7244 	fabric_switch = ((ndlp->nlp_DID == FABRIC_DID) ? 1 : 0);
7245 
7246 	EMLXS_MSGF(EMLXS_CONTEXT,
7247 	    &emlxs_fcsp_complete_msg,
7248 	    "did=0x%x status=%d sbp=%p ubp=%p",
7249 	    ndlp->nlp_DID, status, node_dhc->deferred_sbp,
7250 	    node_dhc->deferred_ubp);
7251 
7252 	if (status == 1) {
7253 		if (fabric_switch) {
7254 			/* Virtual link down */
7255 			(void) emlxs_port_offline(port, 0xfeffffff);
7256 		} else if (!fabric) {
7257 			/* Port offline */
7258 			(void) emlxs_port_offline(port, ndlp->nlp_DID);
7259 		}
7260 	}
7261 	/* Send a LOGO if authentication was not successful */
7262 	if (status == 1) {
7263 		EMLXS_MSGF(EMLXS_CONTEXT,
7264 		    &emlxs_fcsp_complete_msg,
7265 		    "Sending LOGO to did=0x%x...",
7266 		    ndlp->nlp_DID);
7267 		emlxs_send_logo(port, ndlp->nlp_DID);
7268 	}
7269 
7270 	/* Process deferred cmpl now */
7271 	emlxs_mb_deferred_cmpl(port, status,
7272 	    (emlxs_buf_t *)node_dhc->deferred_sbp,
7273 	    (fc_unsol_buf_t *)node_dhc->deferred_ubp, 0);
7274 
7275 	node_dhc->deferred_sbp = 0;
7276 	node_dhc->deferred_ubp = 0;
7277 
7278 	return;
7279 
7280 } /* emlxs_dhc_auth_complete */
7281 
7282 
7283 extern void
emlxs_dhc_attach(emlxs_hba_t * hba)7284 emlxs_dhc_attach(emlxs_hba_t *hba)
7285 {
7286 	mutex_init(&hba->auth_lock, NULL, MUTEX_DRIVER, NULL);
7287 
7288 	mutex_init(&hba->dhc_lock, NULL, MUTEX_DRIVER, NULL);
7289 
7290 	emlxs_auth_cfg_init(hba);
7291 
7292 	emlxs_auth_key_init(hba);
7293 
7294 	hba->rdn_flag = 1;
7295 
7296 	return;
7297 
7298 } /* emlxs_dhc_attach() */
7299 
7300 
7301 extern void
emlxs_dhc_detach(emlxs_hba_t * hba)7302 emlxs_dhc_detach(emlxs_hba_t *hba)
7303 {
7304 	emlxs_auth_cfg_fini(hba);
7305 
7306 	emlxs_auth_key_fini(hba);
7307 
7308 	mutex_destroy(&hba->dhc_lock);
7309 	mutex_destroy(&hba->auth_lock);
7310 
7311 	return;
7312 
7313 } /* emlxs_dhc_detach() */
7314 
7315 
7316 extern void
emlxs_dhc_init_sp(emlxs_port_t * port,uint32_t did,SERV_PARM * sp,char ** msg)7317 emlxs_dhc_init_sp(emlxs_port_t *port, uint32_t did, SERV_PARM *sp, char **msg)
7318 {
7319 	emlxs_hba_t *hba = HBA;
7320 	emlxs_config_t *cfg = &CFG;
7321 	uint32_t fabric;
7322 	uint32_t fabric_switch;
7323 	emlxs_auth_cfg_t *auth_cfg = NULL;
7324 	emlxs_auth_key_t *auth_key = NULL;
7325 
7326 	fabric = ((did & FABRIC_DID_MASK) == FABRIC_DID_MASK) ? 1 : 0;
7327 	fabric_switch = ((did == FABRIC_DID) ? 1 : 0);
7328 
7329 	/* Return is authentication is not enabled */
7330 	if (cfg[CFG_AUTH_ENABLE].current == 0) {
7331 		sp->cmn.fcsp_support = 0;
7332 		bcopy("fcsp:Disabled (0)", (void *) &msg[0],
7333 		    sizeof ("fcsp:Disabled (0)"));
7334 		return;
7335 	}
7336 
7337 	if (port->vpi != 0 && cfg[CFG_AUTH_NPIV].current == 0) {
7338 		sp->cmn.fcsp_support = 0;
7339 		bcopy("fcsp:Disabled (npiv)", (void *) &msg[0],
7340 		    sizeof ("fcsp:Disabled (npiv)"));
7341 		return;
7342 	}
7343 	if (!fabric_switch && fabric) {
7344 		sp->cmn.fcsp_support = 0;
7345 		bcopy("fcsp:Disabled (fs)", (void *) &msg[0],
7346 		    sizeof ("fcsp:Disabled (fs)"));
7347 		return;
7348 	}
7349 	/* Return if fcsp support to this node is not enabled */
7350 	if (!fabric_switch && cfg[CFG_AUTH_E2E].current == 0) {
7351 		sp->cmn.fcsp_support = 0;
7352 		bcopy("fcsp:Disabled (e2e)", (void *) &msg[0],
7353 		    sizeof ("fcsp:Disabled (e2e)"));
7354 		return;
7355 	}
7356 
7357 	mutex_enter(&hba->auth_lock);
7358 	if (fabric_switch) {
7359 		auth_cfg = emlxs_auth_cfg_find(port,
7360 		    (uint8_t *)emlxs_fabric_wwn);
7361 		auth_key = emlxs_auth_key_find(port,
7362 		    (uint8_t *)emlxs_fabric_wwn);
7363 		if ((!auth_cfg) || (!auth_key)) {
7364 			sp->cmn.fcsp_support = 0;
7365 			bcopy("fcsp:Disabled (1)", (void *) &msg[0],
7366 			    sizeof ("fcsp:Disabled (1)"));
7367 			mutex_exit(&hba->auth_lock);
7368 			return;
7369 		}
7370 	}
7371 	mutex_exit(&hba->auth_lock);
7372 
7373 	sp->cmn.fcsp_support = 1;
7374 
7375 	return;
7376 
7377 } /* emlxs_dhc_init_sp() */
7378 
7379 
7380 extern uint32_t
emlxs_dhc_verify_login(emlxs_port_t * port,uint32_t sid,SERV_PARM * sp)7381 emlxs_dhc_verify_login(emlxs_port_t *port, uint32_t sid, SERV_PARM *sp)
7382 {
7383 	emlxs_hba_t *hba = HBA;
7384 	emlxs_config_t *cfg = &CFG;
7385 	emlxs_auth_cfg_t *auth_cfg;
7386 	emlxs_auth_key_t *auth_key;
7387 	uint32_t fabric;
7388 	uint32_t fabric_switch;
7389 
7390 	fabric = ((sid & FABRIC_DID_MASK) == FABRIC_DID_MASK) ? 1 : 0;
7391 	fabric_switch = ((sid == FABRIC_DID) ? 1 : 0);
7392 
7393 	if (port->port_dhc.state == ELX_FABRIC_AUTH_FAILED) {
7394 		/* Reject login */
7395 		return (1);
7396 	}
7397 	/* Remote host supports FCSP */
7398 	if (sp->cmn.fcsp_support) {
7399 		/* Continue login */
7400 		return (0);
7401 	}
7402 	/* Auth disabled in host */
7403 	if (cfg[CFG_AUTH_ENABLE].current == 0) {
7404 		/* Continue login */
7405 		return (0);
7406 	}
7407 	/* Auth disabled for npiv */
7408 	if (port->vpi != 0 && cfg[CFG_AUTH_NPIV].current == 0) {
7409 		/* Continue login */
7410 		return (0);
7411 	}
7412 	if (!fabric_switch && fabric) {
7413 		/* Continue login */
7414 		return (0);
7415 	}
7416 	/* Auth disabled for p2p */
7417 	if (!fabric_switch && cfg[CFG_AUTH_E2E].current == 0) {
7418 		/* Continue login */
7419 		return (0);
7420 	}
7421 
7422 	/* Remote port does NOT support FCSP */
7423 	/* Host has FCSP enabled */
7424 	/* Now check to make sure auth mode for this port is also enabled */
7425 
7426 	mutex_enter(&hba->auth_lock);
7427 
7428 	/* Acquire auth configuration */
7429 	if (fabric_switch) {
7430 		auth_cfg = emlxs_auth_cfg_find(port,
7431 		    (uint8_t *)emlxs_fabric_wwn);
7432 		auth_key = emlxs_auth_key_find(port,
7433 		    (uint8_t *)emlxs_fabric_wwn);
7434 	} else {
7435 		auth_cfg = emlxs_auth_cfg_find(port,
7436 		    (uint8_t *)&sp->portName);
7437 		auth_key = emlxs_auth_key_find(port,
7438 		    (uint8_t *)&sp->portName);
7439 	}
7440 
7441 	if (auth_key && auth_cfg &&
7442 	    (auth_cfg->authentication_mode == AUTH_MODE_ACTIVE)) {
7443 		mutex_exit(&hba->auth_lock);
7444 
7445 		/* Reject login */
7446 		return (1);
7447 	}
7448 	mutex_exit(&hba->auth_lock);
7449 
7450 	return (0);
7451 
7452 } /* emlxs_dhc_verify_login() */
7453 
7454 
7455 /*
7456  * ! emlxs_dhc_reauth_timeout
7457  *
7458  * \pre \post \param phba \param arg1: \param arg2: ndlp to which the host
7459  * is to be authenticated. \return void
7460  *
7461  * \b Description:
7462  *
7463  * Timeout handler for reauthentication heartbeat.
7464  *
7465  * The reauthentication heart beat will be triggered 1 min by default after
7466  * the first authentication success. reauth_intval is
7467  * configurable. if reauth_intval is set to zero, it means no reauth heart
7468  * beat anymore.
7469  *
7470  * reauth heart beat will be triggered by IOCTL call from user space. Reauth
7471  * heart beat will go through the authentication process
7472  * all over again without causing IO traffic disruption. Initially it should
7473  * be triggered after authentication success.
7474  * Subsequently disable/enable reauth heart beat will be performed by
7475  * HBAnyware or other utility.
7476  *
7477  */
7478 /* ARGSUSED */
7479 extern void
emlxs_dhc_reauth_timeout(emlxs_port_t * port,void * arg1,void * arg2)7480 emlxs_dhc_reauth_timeout(
7481 	emlxs_port_t *port,
7482 	void *arg1,
7483 	void *arg2)
7484 {
7485 	emlxs_port_dhc_t *port_dhc = &port->port_dhc;
7486 	NODELIST *ndlp = (NODELIST *) arg2;
7487 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
7488 
7489 	if (node_dhc->auth_cfg.reauthenticate_time_interval == 0) {
7490 		EMLXS_MSGF(EMLXS_CONTEXT,
7491 		    &emlxs_fcsp_debug_msg,
7492 		    "Reauth timeout. Reauth no longer enabled. 0x%x %x",
7493 		    ndlp->nlp_DID, node_dhc->state);
7494 
7495 		emlxs_dhc_set_reauth_time(port, ndlp, DISABLE);
7496 
7497 		return;
7498 	}
7499 	/* This should not happen!! */
7500 	if (port_dhc->state == ELX_FABRIC_IN_AUTH) {
7501 		EMLXS_MSGF(EMLXS_CONTEXT,
7502 		    &emlxs_fcsp_error_msg,
7503 		    "Reauth timeout. Fabric in auth. Quiting. 0x%x %x",
7504 		    ndlp->nlp_DID, node_dhc->state);
7505 
7506 		emlxs_dhc_set_reauth_time(port, ndlp, DISABLE);
7507 
7508 		return;
7509 	}
7510 	if (node_dhc->state != NODE_STATE_AUTH_SUCCESS) {
7511 		EMLXS_MSGF(EMLXS_CONTEXT,
7512 		    &emlxs_fcsp_debug_msg,
7513 		    "Reauth timeout. Auth not done. Restarting. 0x%x %x",
7514 		    ndlp->nlp_DID, node_dhc->state);
7515 
7516 		goto restart;
7517 	}
7518 	/*
7519 	 * This might happen, the ndlp is doing reauthencation. meaning ndlp
7520 	 * is being re-authenticated to the host. Thus not necessary to have
7521 	 * host re-authenticated to the ndlp at this point because ndlp might
7522 	 * support bi-directional auth. we can just simply donothing and
7523 	 * restart the timer.
7524 	 */
7525 	if (port_dhc->state == ELX_FABRIC_IN_REAUTH) {
7526 		EMLXS_MSGF(EMLXS_CONTEXT,
7527 		    &emlxs_fcsp_debug_msg,
7528 		    "Reauth timeout. Fabric in reauth. Restarting. 0x%x %x",
7529 		    ndlp->nlp_DID, node_dhc->state);
7530 
7531 		goto restart;
7532 	}
7533 	/*
7534 	 * node's reauth heart beat is running already, cancel it first and
7535 	 * then restart
7536 	 */
7537 	if (node_dhc->nlp_reauth_status == NLP_HOST_REAUTH_IN_PROGRESS) {
7538 		EMLXS_MSGF(EMLXS_CONTEXT,
7539 		    &emlxs_fcsp_debug_msg,
7540 		    "Reauth timeout. Fabric in reauth. Restarting. 0x%x %x",
7541 		    ndlp->nlp_DID, node_dhc->state);
7542 
7543 		goto restart;
7544 	}
7545 	EMLXS_MSGF(EMLXS_CONTEXT,
7546 	    &emlxs_fcsp_debug_msg,
7547 	    "Reauth timeout. Auth initiated. did=0x%x",
7548 	    ndlp->nlp_DID);
7549 
7550 	emlxs_dhc_set_reauth_time(port, ndlp, ENABLE);
7551 	node_dhc->nlp_reauth_status = NLP_HOST_REAUTH_IN_PROGRESS;
7552 
7553 	/* Attempt to restart authentication */
7554 	if (emlxs_dhc_auth_start(port, ndlp, NULL, NULL) != 0) {
7555 		EMLXS_MSGF(EMLXS_CONTEXT,
7556 		    &emlxs_fcsp_debug_msg,
7557 		    "Reauth timeout. Auth initiation failed. 0x%x %x",
7558 		    ndlp->nlp_DID, node_dhc->state);
7559 
7560 		return;
7561 	}
7562 	return;
7563 
7564 restart:
7565 
7566 	emlxs_dhc_set_reauth_time(port, ndlp, ENABLE);
7567 
7568 	return;
7569 
7570 } /* emlxs_dhc_reauth_timeout */
7571 
7572 
7573 static void
emlxs_dhc_set_reauth_time(emlxs_port_t * port,emlxs_node_t * ndlp,uint32_t status)7574 emlxs_dhc_set_reauth_time(
7575 	emlxs_port_t *port,
7576 	emlxs_node_t *ndlp,
7577 	uint32_t status)
7578 {
7579 	emlxs_port_dhc_t *port_dhc = &port->port_dhc;
7580 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
7581 	uint32_t drv_time;
7582 	uint32_t timeout;
7583 	uint32_t reauth_tmo;
7584 	time_t last_auth_time;
7585 
7586 	node_dhc->flag &= ~NLP_SET_REAUTH_TIME;
7587 
7588 	if ((status == ENABLE) &&
7589 	    node_dhc->auth_cfg.reauthenticate_time_interval) {
7590 
7591 		timeout =
7592 		    (60 * node_dhc->auth_cfg.reauthenticate_time_interval);
7593 		drv_time = DRV_TIME;
7594 
7595 		/* Get last successful auth time */
7596 		if (ndlp->nlp_DID == FABRIC_DID) {
7597 			last_auth_time = port_dhc->auth_time;
7598 		} else if (node_dhc->parent_auth_cfg) {
7599 			last_auth_time = node_dhc->parent_auth_cfg->auth_time;
7600 		} else {
7601 			last_auth_time = 0;
7602 		}
7603 
7604 		if (last_auth_time) {
7605 			reauth_tmo = last_auth_time + timeout;
7606 
7607 			/* Validate reauth_tmo */
7608 			if ((reauth_tmo < drv_time) ||
7609 			    (reauth_tmo > drv_time + timeout)) {
7610 				reauth_tmo = drv_time + timeout;
7611 			}
7612 		} else {
7613 			reauth_tmo = drv_time + timeout;
7614 		}
7615 
7616 		node_dhc->nlp_reauth_tmo = reauth_tmo;
7617 		node_dhc->nlp_reauth_status = NLP_HOST_REAUTH_ENABLED;
7618 
7619 		EMLXS_MSGF(EMLXS_CONTEXT,
7620 		    &emlxs_fcsp_debug_msg,
7621 		    "Reauth enabled. did=0x%x state=%x tmo=%d,%d",
7622 		    ndlp->nlp_DID, node_dhc->state,
7623 		    node_dhc->auth_cfg.reauthenticate_time_interval,
7624 		    (reauth_tmo - drv_time));
7625 
7626 	} else {
7627 		node_dhc->nlp_reauth_tmo = 0;
7628 		node_dhc->nlp_reauth_status = NLP_HOST_REAUTH_DISABLED;
7629 
7630 		EMLXS_MSGF(EMLXS_CONTEXT,
7631 		    &emlxs_fcsp_debug_msg,
7632 		    "Reauth disabled. did=0x%x state=%x",
7633 		    ndlp->nlp_DID, node_dhc->state);
7634 	}
7635 
7636 	return;
7637 
7638 } /* emlxs_dhc_set_reauth_time */
7639 
7640 
7641 /* ARGSUSED */
7642 extern void
emlxs_dhc_authrsp_timeout(emlxs_port_t * port,void * arg1,void * arg2)7643 emlxs_dhc_authrsp_timeout(
7644 	emlxs_port_t *port,
7645 	void *arg1,
7646 	void *arg2)
7647 {
7648 	NODELIST *ndlp = (NODELIST *)arg1;
7649 	emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
7650 	uint8_t ReasonCode;
7651 	uint8_t ReasonCodeExplanation;
7652 
7653 	node_dhc->nlp_authrsp_tmo = 0;
7654 	node_dhc->nlp_authrsp_tmocnt++;
7655 
7656 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_debug_msg,
7657 	    "Authrsp timeout. did=0x%x count=%d",
7658 	    ndlp->nlp_DID, node_dhc->nlp_authrsp_tmocnt);
7659 
7660 	/*
7661 	 * According to the FC-SP spec v1.8 pp76.
7662 	 *
7663 	 * When the AUTH_TMO error is detected, the entity may: 1. Act as if the
7664 	 * authentication transaction has failed and terminate the
7665 	 * communication; or 2. Restart a new authentication transaction, by
7666 	 * sending an AUTH_Reject msg with Reason Code `Logical Error' and
7667 	 * Reason Code Explanation 'Restart Authentication Protocol', The
7668 	 * action performed by the entity receiving such a AUTH_Reject should
7669 	 * restart the authentication Transaction by sending a new
7670 	 * AUTH_Negotiate. We plan to use 2 as the action for now.
7671 	 *
7672 	 */
7673 
7674 	if (node_dhc->nlp_authrsp_tmocnt > 3) {
7675 		/* Generate a remove event for the nodelist entry */
7676 		(void) emlxs_dhchap_state_machine(port, NULL, NULL,
7677 		    NULL, ndlp, NODE_EVENT_DEVICE_RM);
7678 
7679 		ReasonCode = AUTHRJT_FAILURE;
7680 		ReasonCodeExplanation = AUTHEXP_AUTH_FAILED;
7681 	} else {
7682 		/* Generate a recovery event for the nodelist entry */
7683 		(void) emlxs_dhchap_state_machine(port, NULL, NULL,
7684 		    NULL, ndlp, NODE_EVENT_DEVICE_RECOVERY);
7685 
7686 		ReasonCode = AUTHRJT_LOGIC_ERR;
7687 		ReasonCodeExplanation = AUTHEXP_RESTART_AUTH;
7688 	}
7689 
7690 	emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_FAILED, ReasonCode,
7691 	    ReasonCodeExplanation);
7692 	(void) emlxs_issue_auth_reject(port, ndlp, 0, 0, ReasonCode,
7693 	    ReasonCodeExplanation);
7694 	emlxs_dhc_auth_complete(port, ndlp, 1);
7695 
7696 	/*
7697 	 * It is expected the other party should restart the authentication
7698 	 * transaction
7699 	 */
7700 
7701 	return;
7702 
7703 } /* emlxs_dhc_authrsp_timeout() */
7704 
7705 
7706 /* **************************** AUTH CFG MANAGEMENT ************************ */
7707 
7708 /* auth_lock must be held */
7709 static emlxs_auth_cfg_t *
emlxs_auth_cfg_find(emlxs_port_t * port,uint8_t * rwwpn)7710 emlxs_auth_cfg_find(emlxs_port_t *port, uint8_t *rwwpn)
7711 {
7712 	emlxs_hba_t *hba = HBA;
7713 	emlxs_auth_cfg_t *auth_cfg;
7714 
7715 	if (rwwpn) {
7716 		/* lwwpn, rwwpn */
7717 		auth_cfg = emlxs_auth_cfg_get(hba,
7718 		    (uint8_t *)&port->wwpn, (uint8_t *)rwwpn);
7719 
7720 		if (auth_cfg) {
7721 			emlxs_auth_cfg_print(hba, auth_cfg);
7722 			return (auth_cfg);
7723 		}
7724 		/* null, rwwpn */
7725 		auth_cfg = emlxs_auth_cfg_get(hba,
7726 		    (uint8_t *)emlxs_null_wwn, (uint8_t *)rwwpn);
7727 
7728 		if (auth_cfg) {
7729 			emlxs_auth_cfg_print(hba, auth_cfg);
7730 			return (auth_cfg);
7731 		}
7732 	}
7733 	/* lwwpn, null */
7734 	auth_cfg = emlxs_auth_cfg_get(hba,
7735 	    (uint8_t *)&port->wwpn, (uint8_t *)emlxs_null_wwn);
7736 
7737 	if (auth_cfg) {
7738 		emlxs_auth_cfg_print(hba, auth_cfg);
7739 		return (auth_cfg);
7740 	}
7741 	/* null, null */
7742 	return (&hba->auth_cfg);
7743 
7744 } /* emlxs_auth_cfg_find() */
7745 
7746 static void
emlxs_auth_cfg_init(emlxs_hba_t * hba)7747 emlxs_auth_cfg_init(emlxs_hba_t *hba)
7748 {
7749 	emlxs_config_t *cfg = &CFG;
7750 	emlxs_auth_cfg_t *auth_cfg;
7751 
7752 	/* Destroy old table if one exists */
7753 	emlxs_auth_cfg_fini(hba);
7754 
7755 	mutex_enter(&hba->auth_lock);
7756 
7757 	/* Zero default entry */
7758 	auth_cfg = &hba->auth_cfg;
7759 	bzero(auth_cfg, sizeof (emlxs_auth_cfg_t));
7760 	auth_cfg->next = auth_cfg;
7761 	auth_cfg->prev = auth_cfg;
7762 
7763 	/* Configure the default entry */
7764 	auth_cfg->authentication_timeout =
7765 	    cfg[CFG_AUTH_TMO].current;
7766 	auth_cfg->authentication_mode =
7767 	    cfg[CFG_AUTH_MODE].current;
7768 	auth_cfg->bidirectional =
7769 	    cfg[CFG_AUTH_BIDIR].current;
7770 	auth_cfg->authentication_type_priority[0] =
7771 	    (cfg[CFG_AUTH_TYPE].current & 0xF000) >> 12;
7772 	auth_cfg->authentication_type_priority[1] =
7773 	    (cfg[CFG_AUTH_TYPE].current & 0x0F00) >> 8;
7774 	auth_cfg->authentication_type_priority[2] =
7775 	    (cfg[CFG_AUTH_TYPE].current & 0x00F0) >> 4;
7776 	auth_cfg->authentication_type_priority[3] =
7777 	    (cfg[CFG_AUTH_TYPE].current & 0x000F);
7778 	auth_cfg->hash_priority[0] =
7779 	    (cfg[CFG_AUTH_HASH].current & 0xF000) >> 12;
7780 	auth_cfg->hash_priority[1] =
7781 	    (cfg[CFG_AUTH_HASH].current & 0x0F00) >> 8;
7782 	auth_cfg->hash_priority[2] =
7783 	    (cfg[CFG_AUTH_HASH].current & 0x00F0) >> 4;
7784 	auth_cfg->hash_priority[3] =
7785 	    (cfg[CFG_AUTH_HASH].current & 0x000F);
7786 	auth_cfg->dh_group_priority[0] =
7787 	    (cfg[CFG_AUTH_GROUP].current & 0xF0000000) >> 28;
7788 	auth_cfg->dh_group_priority[1] =
7789 	    (cfg[CFG_AUTH_GROUP].current & 0x0F000000) >> 24;
7790 	auth_cfg->dh_group_priority[2] =
7791 	    (cfg[CFG_AUTH_GROUP].current & 0x00F00000) >> 20;
7792 	auth_cfg->dh_group_priority[3] =
7793 	    (cfg[CFG_AUTH_GROUP].current & 0x000F0000) >> 16;
7794 	auth_cfg->dh_group_priority[4] =
7795 	    (cfg[CFG_AUTH_GROUP].current & 0x0000F000) >> 12;
7796 	auth_cfg->dh_group_priority[5] =
7797 	    (cfg[CFG_AUTH_GROUP].current & 0x00000F00) >> 8;
7798 	auth_cfg->dh_group_priority[6] =
7799 	    (cfg[CFG_AUTH_GROUP].current & 0x000000F0) >> 4;
7800 	auth_cfg->dh_group_priority[7] =
7801 	    (cfg[CFG_AUTH_GROUP].current & 0x0000000F);
7802 	auth_cfg->reauthenticate_time_interval =
7803 	    cfg[CFG_AUTH_INTERVAL].current;
7804 
7805 	emlxs_auth_cfg_read(hba);
7806 
7807 	mutex_exit(&hba->auth_lock);
7808 
7809 	return;
7810 
7811 } /* emlxs_auth_cfg_init() */
7812 
7813 
7814 static void
emlxs_auth_cfg_fini(emlxs_hba_t * hba)7815 emlxs_auth_cfg_fini(emlxs_hba_t *hba)
7816 {
7817 	emlxs_auth_cfg_t *auth_cfg = hba->auth_cfg.next;
7818 	emlxs_auth_cfg_t *next;
7819 
7820 	mutex_enter(&hba->auth_lock);
7821 
7822 	while (auth_cfg && auth_cfg != &hba->auth_cfg) {
7823 		next = auth_cfg->next;
7824 		emlxs_auth_cfg_destroy(hba, auth_cfg);
7825 		auth_cfg = next;
7826 	}
7827 
7828 	mutex_exit(&hba->auth_lock);
7829 
7830 	return;
7831 
7832 } /* emlxs_auth_cfg_fini() */
7833 
7834 
7835 static void
emlxs_auth_cfg_print(emlxs_hba_t * hba,emlxs_auth_cfg_t * auth_cfg)7836 emlxs_auth_cfg_print(emlxs_hba_t *hba, emlxs_auth_cfg_t *auth_cfg)
7837 {
7838 	emlxs_port_t *port = &PPORT;
7839 
7840 	char s_lwwpn[32];
7841 	char s_rwwpn[32];
7842 
7843 	/* Create and add new entry */
7844 	EMLXS_MSGF(EMLXS_CONTEXT,
7845 	    &emlxs_fcsp_detail_msg,
7846 	    "%s:%s:%x:%x:%x:%x%x%x%x:%x%x%x%x:%x%x%x%x%x%x%x%x:%x",
7847 	    emlxs_wwn_xlate(s_lwwpn, sizeof (s_lwwpn),
7848 	    (uint8_t *)&auth_cfg->local_entity),
7849 	    emlxs_wwn_xlate(s_rwwpn, sizeof (s_rwwpn),
7850 	    (uint8_t *)&auth_cfg->remote_entity),
7851 	    auth_cfg->authentication_timeout,
7852 	    auth_cfg->authentication_mode,
7853 	    auth_cfg->bidirectional,
7854 	    auth_cfg->authentication_type_priority[0],
7855 	    auth_cfg->authentication_type_priority[1],
7856 	    auth_cfg->authentication_type_priority[2],
7857 	    auth_cfg->authentication_type_priority[3],
7858 	    auth_cfg->hash_priority[0],
7859 	    auth_cfg->hash_priority[1],
7860 	    auth_cfg->hash_priority[2],
7861 	    auth_cfg->hash_priority[3],
7862 	    auth_cfg->dh_group_priority[0],
7863 	    auth_cfg->dh_group_priority[1],
7864 	    auth_cfg->dh_group_priority[2],
7865 	    auth_cfg->dh_group_priority[3],
7866 	    auth_cfg->dh_group_priority[4],
7867 	    auth_cfg->dh_group_priority[5],
7868 	    auth_cfg->dh_group_priority[6],
7869 	    auth_cfg->dh_group_priority[7],
7870 	    auth_cfg->reauthenticate_time_interval);
7871 
7872 } /* emlxs_auth_cfg_print() */
7873 
7874 
7875 /* auth_lock must be held */
7876 static emlxs_auth_cfg_t *
emlxs_auth_cfg_get(emlxs_hba_t * hba,uint8_t * lwwpn,uint8_t * rwwpn)7877 emlxs_auth_cfg_get(emlxs_hba_t *hba, uint8_t *lwwpn, uint8_t *rwwpn)
7878 {
7879 	emlxs_auth_cfg_t *auth_cfg;
7880 
7881 	if (!lwwpn || !rwwpn) {
7882 		return (NULL);
7883 	}
7884 
7885 	/* Check for default entry */
7886 	if ((bcmp(lwwpn, emlxs_null_wwn, 8) == 0) &&
7887 	    (bcmp(rwwpn, emlxs_null_wwn, 8) == 0)) {
7888 		return (&hba->auth_cfg);
7889 	}
7890 
7891 	for (auth_cfg = hba->auth_cfg.next;
7892 	    auth_cfg != &hba->auth_cfg; auth_cfg = auth_cfg->next) {
7893 		/* Find pwd entry for this local port */
7894 
7895 		/* Check for exact wwpn match */
7896 		if (bcmp((void *)&auth_cfg->local_entity,
7897 		    (void *)lwwpn, 8) != 0) {
7898 			continue;
7899 		}
7900 		/* Find pwd entry for remote port */
7901 
7902 		/* Check for exact wwpn match */
7903 		if (bcmp((void *)&auth_cfg->remote_entity,
7904 		    (void *)rwwpn, 8) != 0) {
7905 			continue;
7906 		}
7907 		return (auth_cfg);
7908 	}
7909 
7910 	return (NULL);
7911 
7912 } /* emlxs_auth_cfg_get() */
7913 
7914 
7915 /* auth_lock must be held */
7916 static emlxs_auth_cfg_t *
emlxs_auth_cfg_create(emlxs_hba_t * hba,uint8_t * lwwpn,uint8_t * rwwpn)7917 emlxs_auth_cfg_create(emlxs_hba_t *hba, uint8_t *lwwpn, uint8_t *rwwpn)
7918 {
7919 	emlxs_auth_cfg_t *auth_cfg;
7920 
7921 	/* First check if entry already exists */
7922 	auth_cfg = emlxs_auth_cfg_get(hba, lwwpn, rwwpn);
7923 
7924 	if (auth_cfg) {
7925 		return (auth_cfg);
7926 	}
7927 	/* Allocate entry */
7928 	auth_cfg = (emlxs_auth_cfg_t *)kmem_zalloc(sizeof (emlxs_auth_cfg_t),
7929 	    KM_NOSLEEP);
7930 
7931 	if (!auth_cfg) {
7932 		return (NULL);
7933 	}
7934 	/* Add to list */
7935 	auth_cfg->next = &hba->auth_cfg;
7936 	auth_cfg->prev = hba->auth_cfg.prev;
7937 	hba->auth_cfg.prev->next = auth_cfg;
7938 	hba->auth_cfg.prev = auth_cfg;
7939 	hba->auth_cfg_count++;
7940 
7941 	/* Initialize name pair */
7942 	if (lwwpn) {
7943 		bcopy((void *)lwwpn, (void *)&auth_cfg->local_entity, 8);
7944 	}
7945 	if (rwwpn) {
7946 		bcopy((void *)rwwpn, (void *)&auth_cfg->remote_entity, 8);
7947 	}
7948 	auth_cfg->auth_status.auth_state = DFC_AUTH_STATE_OFF;
7949 
7950 	return (auth_cfg);
7951 
7952 } /* emlxs_auth_cfg_create() */
7953 
7954 
7955 /* auth_lock must be held */
7956 static void
emlxs_auth_cfg_destroy(emlxs_hba_t * hba,emlxs_auth_cfg_t * auth_cfg)7957 emlxs_auth_cfg_destroy(emlxs_hba_t *hba, emlxs_auth_cfg_t *auth_cfg)
7958 {
7959 
7960 	if (!auth_cfg) {
7961 		return;
7962 	}
7963 	if (auth_cfg == &hba->auth_cfg) {
7964 		return;
7965 	}
7966 	/* Remove from  list */
7967 	auth_cfg->next->prev = auth_cfg->prev;
7968 	auth_cfg->prev->next = auth_cfg->next;
7969 	hba->auth_cfg_count--;
7970 
7971 	/* Remove node binding */
7972 	if (auth_cfg->node &&
7973 	    auth_cfg->node->nlp_active &&
7974 	    (auth_cfg->node->node_dhc.parent_auth_cfg == auth_cfg)) {
7975 		auth_cfg->node->node_dhc.parent_auth_cfg = NULL;
7976 	}
7977 	bzero(auth_cfg, sizeof (emlxs_auth_cfg_t));
7978 	kmem_free(auth_cfg, sizeof (emlxs_auth_cfg_t));
7979 
7980 	return;
7981 
7982 } /* emlxs_auth_cfg_destroy() */
7983 
7984 
7985 /* auth_lock must be held */
7986 static void
emlxs_auth_cfg_read(emlxs_hba_t * hba)7987 emlxs_auth_cfg_read(emlxs_hba_t *hba)
7988 {
7989 	emlxs_port_t *port = &PPORT;
7990 	char **arrayp;
7991 	emlxs_auth_cfg_t auth_cfg;
7992 	emlxs_auth_cfg_t *auth_cfg2;
7993 	uint32_t cnt;
7994 	uint32_t rval;
7995 	char buffer[64];
7996 	char *prop_str;
7997 	uint32_t i;
7998 
7999 	/* Check for the per adapter setting */
8000 	(void) snprintf(buffer, sizeof (buffer), "%s%d-auth-cfgs", DRIVER_NAME,
8001 	    hba->ddiinst);
8002 	cnt = 0;
8003 	arrayp = NULL;
8004 	rval = ddi_prop_lookup_string_array(DDI_DEV_T_ANY, hba->dip,
8005 	    (DDI_PROP_DONTPASS),
8006 	    buffer, &arrayp, &cnt);
8007 
8008 	if ((rval != DDI_PROP_SUCCESS) || !cnt || !arrayp) {
8009 		/* Check for the global setting */
8010 		cnt = 0;
8011 		arrayp = NULL;
8012 		rval = ddi_prop_lookup_string_array(DDI_DEV_T_ANY,
8013 		    hba->dip, (DDI_PROP_DONTPASS),
8014 		    "auth-cfgs", &arrayp, &cnt);
8015 	}
8016 	if ((rval != DDI_PROP_SUCCESS) || !cnt || !arrayp) {
8017 		return;
8018 	}
8019 	for (i = 0; i < cnt; i++) {
8020 		prop_str = arrayp[i];
8021 		if (prop_str == NULL) {
8022 			break;
8023 		}
8024 		/* parse the string */
8025 		if (emlxs_auth_cfg_parse(hba, &auth_cfg, prop_str) == 0) {
8026 			EMLXS_MSGF(EMLXS_CONTEXT,
8027 			    &emlxs_attach_msg,
8028 			    "Error parsing auth_cfgs property. entry=%d", i);
8029 			continue;
8030 		}
8031 		auth_cfg2 = emlxs_auth_cfg_create(hba,
8032 		    (uint8_t *)&auth_cfg.local_entity,
8033 		    (uint8_t *)&auth_cfg.remote_entity);
8034 
8035 		if (!auth_cfg2) {
8036 			EMLXS_MSGF(EMLXS_CONTEXT,
8037 			    &emlxs_attach_msg,
8038 			    "Out of memory parsing auth_cfgs property. ey=%d",
8039 			    i);
8040 			return;
8041 		}
8042 		auth_cfg.next = auth_cfg2->next;
8043 		auth_cfg.prev = auth_cfg2->prev;
8044 		bcopy((uint8_t *)&auth_cfg,
8045 		    (uint8_t *)auth_cfg2,
8046 		    sizeof (emlxs_auth_cfg_t));
8047 	}
8048 
8049 	return;
8050 
8051 } /* emlxs_auth_cfg_read() */
8052 
8053 
8054 /* auth_lock must be held */
8055 static uint32_t
emlxs_auth_cfg_parse(emlxs_hba_t * hba,emlxs_auth_cfg_t * auth_cfg,char * prop_str)8056 emlxs_auth_cfg_parse(
8057 	emlxs_hba_t *hba,
8058 	emlxs_auth_cfg_t *auth_cfg,
8059 	char *prop_str)
8060 {
8061 	emlxs_port_t *port = &PPORT;
8062 	emlxs_config_t *cfg = &CFG;
8063 	uint32_t errors = 0;
8064 	uint32_t c1;
8065 	uint8_t *np;
8066 	uint32_t j;
8067 	uint32_t i;
8068 	uint32_t sum;
8069 	char *s;
8070 
8071 	s = prop_str;
8072 	bzero(auth_cfg, sizeof (emlxs_auth_cfg_t));
8073 
8074 	/* Read local wwpn */
8075 	np = (uint8_t *)&auth_cfg->local_entity;
8076 	for (j = 0; j < 8; j++) {
8077 		c1 = *s++;
8078 		if ((c1 >= '0') && (c1 <= '9')) {
8079 			sum = ((c1 - '0') << 4);
8080 		} else if ((c1 >= 'a') && (c1 <= 'f')) {
8081 			sum = ((c1 - 'a' + 10) << 4);
8082 		} else if ((c1 >= 'A') && (c1 <= 'F')) {
8083 			sum = ((c1 - 'A' + 10) << 4);
8084 		} else {
8085 			EMLXS_MSGF(EMLXS_CONTEXT,
8086 			    &emlxs_attach_debug_msg,
8087 			    "Cfg err:Invalid LWWPN found. byte=%d hi_nibble=%c",
8088 			    j, c1);
8089 			errors++;
8090 		}
8091 
8092 		c1 = *s++;
8093 		if ((c1 >= '0') && (c1 <= '9')) {
8094 			sum |= (c1 - '0');
8095 		} else if ((c1 >= 'a') && (c1 <= 'f')) {
8096 			sum |= (c1 - 'a' + 10);
8097 		} else if ((c1 >= 'A') && (c1 <= 'F')) {
8098 			sum |= (c1 - 'A' + 10);
8099 		} else {
8100 			EMLXS_MSGF(EMLXS_CONTEXT,
8101 			    &emlxs_attach_debug_msg,
8102 			    "Cfg err: Invalid LWWPN found. %d %c",
8103 			    j, c1);
8104 			errors++;
8105 		}
8106 
8107 		*np++ = (uint8_t)sum;
8108 	}
8109 
8110 	if (*s++ != ':') {
8111 		EMLXS_MSGF(EMLXS_CONTEXT,
8112 		    &emlxs_attach_debug_msg,
8113 		    "Cfg err: Invalid delimiter after LWWPN.");
8114 		goto out;
8115 	}
8116 	/* Read remote wwpn */
8117 	np = (uint8_t *)&auth_cfg->remote_entity;
8118 	for (j = 0; j < 8; j++) {
8119 		c1 = *s++;
8120 		if ((c1 >= '0') && (c1 <= '9')) {
8121 			sum = ((c1 - '0') << 4);
8122 		} else if ((c1 >= 'a') && (c1 <= 'f')) {
8123 			sum = ((c1 - 'a' + 10) << 4);
8124 		} else if ((c1 >= 'A') && (c1 <= 'F')) {
8125 			sum = ((c1 - 'A' + 10) << 4);
8126 		} else {
8127 			EMLXS_MSGF(EMLXS_CONTEXT,
8128 			    &emlxs_attach_debug_msg,
8129 			    "Cfg err: Invalid RWWPN found.byte=%d hi_nibble=%c",
8130 			    j, c1);
8131 			errors++;
8132 		}
8133 
8134 		c1 = *s++;
8135 		if ((c1 >= '0') && (c1 <= '9')) {
8136 			sum |= (c1 - '0');
8137 		} else if ((c1 >= 'a') && (c1 <= 'f')) {
8138 			sum |= (c1 - 'a' + 10);
8139 		} else if ((c1 >= 'A') && (c1 <= 'F')) {
8140 			sum |= (c1 - 'A' + 10);
8141 		} else {
8142 			EMLXS_MSGF(EMLXS_CONTEXT,
8143 			    &emlxs_attach_debug_msg,
8144 			    "Cfg err: Invalid RWWPN found. %d %c",
8145 			    j, c1);
8146 			errors++;
8147 		}
8148 
8149 		*np++ = (uint8_t)sum;
8150 	}
8151 
8152 	if (*s++ != ':') {
8153 		EMLXS_MSGF(EMLXS_CONTEXT,
8154 		    &emlxs_attach_debug_msg,
8155 		    "Cfg err: Invalid delimiter after RWWPN.");
8156 		goto out;
8157 	}
8158 	/* Read auth_tov (%x) */
8159 	sum = 0;
8160 	do {
8161 		c1 = *s++;
8162 		if ((c1 >= '0') && (c1 <= '9')) {
8163 			sum = (sum << 4) + (c1 - '0');
8164 		} else if ((c1 >= 'a') && (c1 <= 'f')) {
8165 			sum = (sum << 4) + (c1 - 'a' + 10);
8166 		} else if ((c1 >= 'A') && (c1 <= 'F')) {
8167 			sum = (sum << 4) + (c1 - 'A' + 10);
8168 		} else {
8169 			EMLXS_MSGF(EMLXS_CONTEXT,
8170 			    &emlxs_attach_debug_msg,
8171 			    "Cfg err: Invalid auth_tov found. c=%c sum=%d",
8172 			    c1, sum);
8173 
8174 			errors++;
8175 		}
8176 
8177 	} while (*s != ':' && *s != 0);
8178 	auth_cfg->authentication_timeout = sum;
8179 
8180 	if (*s++ != ':') {
8181 		EMLXS_MSGF(EMLXS_CONTEXT,
8182 		    &emlxs_attach_debug_msg,
8183 		    "Cfg err: Invalid delimiter after auth_tov.");
8184 		goto out;
8185 	}
8186 	/* Read auth_mode */
8187 	sum = 0;
8188 	do {
8189 		c1 = *s++;
8190 		if ((c1 >= '0') && (c1 <= '9')) {
8191 			sum = (sum << 4) + (c1 - '0');
8192 		} else if ((c1 >= 'a') && (c1 <= 'f')) {
8193 			sum = (sum << 4) + (c1 - 'a' + 10);
8194 		} else if ((c1 >= 'A') && (c1 <= 'F')) {
8195 			sum = (sum << 4) + (c1 - 'A' + 10);
8196 		} else {
8197 			EMLXS_MSGF(EMLXS_CONTEXT,
8198 			    &emlxs_attach_debug_msg,
8199 			    "Cfg err: Invalid auth_mode found. c=%c sum=%d",
8200 			    c1, sum);
8201 
8202 			errors++;
8203 		}
8204 
8205 	} while (*s != ':' && *s != 0);
8206 	auth_cfg->authentication_mode = sum;
8207 
8208 	if (*s++ != ':') {
8209 		EMLXS_MSGF(EMLXS_CONTEXT,
8210 		    &emlxs_attach_debug_msg,
8211 		    "Config error: Invalid delimiter after auth_mode.");
8212 		goto out;
8213 	}
8214 	/* Read auth_bidir */
8215 	sum = 0;
8216 	do {
8217 		c1 = *s++;
8218 		if ((c1 >= '0') && (c1 <= '9')) {
8219 			sum = (sum << 4) + (c1 - '0');
8220 		} else if ((c1 >= 'a') && (c1 <= 'f')) {
8221 			sum = (sum << 4) + (c1 - 'a' + 10);
8222 		} else if ((c1 >= 'A') && (c1 <= 'F')) {
8223 			sum = (sum << 4) + (c1 - 'A' + 10);
8224 		} else {
8225 			EMLXS_MSGF(EMLXS_CONTEXT,
8226 			    &emlxs_attach_debug_msg,
8227 			    "Cfg err: Invalid auth_bidir found. c=%c sum=%d",
8228 			    c1, sum);
8229 
8230 			errors++;
8231 		}
8232 
8233 	} while (*s != ':' && *s != 0);
8234 	auth_cfg->bidirectional = sum;
8235 
8236 	if (*s++ != ':') {
8237 		EMLXS_MSGF(EMLXS_CONTEXT,
8238 		    &emlxs_attach_debug_msg,
8239 		    "Cfg err: Invalid delimiter after auth_bidir.");
8240 		goto out;
8241 	}
8242 	/* Read type_priority[4] */
8243 	for (i = 0; i < 4; i++) {
8244 		c1 = *s++;
8245 		if ((c1 >= '0') && (c1 <= '9')) {
8246 			sum = (c1 - '0');
8247 		} else if ((c1 >= 'a') && (c1 <= 'f')) {
8248 			sum = (c1 - 'a' + 10);
8249 		} else if ((c1 >= 'A') && (c1 <= 'F')) {
8250 			sum = (c1 - 'A' + 10);
8251 		} else {
8252 			EMLXS_MSGF(EMLXS_CONTEXT,
8253 			    &emlxs_attach_debug_msg,
8254 			    "Cfg err: Invalid type_pty[%d] found. c=%c sum=%d",
8255 			    i, c1, sum);
8256 
8257 			errors++;
8258 		}
8259 
8260 		auth_cfg->authentication_type_priority[i] = sum;
8261 	}
8262 
8263 	if (*s++ != ':') {
8264 		EMLXS_MSGF(EMLXS_CONTEXT,
8265 		    &emlxs_attach_debug_msg,
8266 		    "Cfg err: Invalid delimiter after type_priority.");
8267 
8268 		goto out;
8269 	}
8270 	/* Read hash_priority[4] */
8271 	for (i = 0; i < 4; i++) {
8272 		c1 = *s++;
8273 		if ((c1 >= '0') && (c1 <= '9')) {
8274 			sum = (c1 - '0');
8275 		} else if ((c1 >= 'a') && (c1 <= 'f')) {
8276 			sum = (c1 - 'a' + 10);
8277 		} else if ((c1 >= 'A') && (c1 <= 'F')) {
8278 			sum = (c1 - 'A' + 10);
8279 		} else {
8280 			EMLXS_MSGF(EMLXS_CONTEXT,
8281 			    &emlxs_attach_debug_msg,
8282 			    "Cfg err: Invalid hash_priority[%d] fd. %c %d",
8283 			    i, c1, sum);
8284 
8285 			errors++;
8286 		}
8287 
8288 		auth_cfg->hash_priority[i] = sum;
8289 	}
8290 
8291 	if (*s++ != ':') {
8292 		EMLXS_MSGF(EMLXS_CONTEXT,
8293 		    &emlxs_attach_debug_msg,
8294 		    "Cfg err: Invalid delimiter after hash_priority.");
8295 
8296 		goto out;
8297 	}
8298 	/* Read group_priority[8] */
8299 	for (i = 0; i < 8; i++) {
8300 		c1 = *s++;
8301 		if ((c1 >= '0') && (c1 <= '9')) {
8302 			sum = (c1 - '0');
8303 		} else if ((c1 >= 'a') && (c1 <= 'f')) {
8304 			sum = (c1 - 'a' + 10);
8305 		} else if ((c1 >= 'A') && (c1 <= 'F')) {
8306 			sum = (c1 - 'A' + 10);
8307 		} else {
8308 			EMLXS_MSGF(EMLXS_CONTEXT,
8309 			    &emlxs_attach_debug_msg,
8310 			    "Cfg err: Invalid group_priority[%d] fd. %c %d",
8311 			    i, c1, sum);
8312 
8313 			errors++;
8314 		}
8315 
8316 		auth_cfg->dh_group_priority[i] = sum;
8317 	}
8318 
8319 	if (*s++ != ':') {
8320 		EMLXS_MSGF(EMLXS_CONTEXT,
8321 		    &emlxs_attach_debug_msg,
8322 		    "Cfg err: Invalid delimiter after group_priority.");
8323 		goto out;
8324 	}
8325 	/* Read reauth_tov */
8326 	sum = 0;
8327 	do {
8328 		c1 = *s++;
8329 		if ((c1 >= '0') && (c1 <= '9')) {
8330 			sum = (sum << 4) + (c1 - '0');
8331 		} else if ((c1 >= 'a') && (c1 <= 'f')) {
8332 			sum = (sum << 4) + (c1 - 'a' + 10);
8333 		} else if ((c1 >= 'A') && (c1 <= 'F')) {
8334 			sum = (sum << 4) + (c1 - 'A' + 10);
8335 		} else {
8336 			EMLXS_MSGF(EMLXS_CONTEXT,
8337 			    &emlxs_attach_debug_msg,
8338 			    "Cfg err: Invalid reauth_tov found. c=%c sum=%d",
8339 			    c1, sum);
8340 
8341 			errors++;
8342 		}
8343 
8344 	} while (*s != ':' && *s != 0);
8345 	auth_cfg->reauthenticate_time_interval = sum;
8346 
8347 	if (errors) {
8348 		goto out;
8349 	}
8350 	/* Verify values */
8351 
8352 	/* Check authentication_timeout */
8353 	if (auth_cfg->authentication_timeout < cfg[CFG_AUTH_TMO].low) {
8354 		auth_cfg->authentication_timeout = cfg[CFG_AUTH_TMO].current;
8355 	} else if (auth_cfg->authentication_timeout > cfg[CFG_AUTH_TMO].hi) {
8356 		auth_cfg->authentication_timeout = cfg[CFG_AUTH_TMO].current;
8357 	}
8358 	/* Check authentication_mode */
8359 	if (auth_cfg->authentication_mode < cfg[CFG_AUTH_MODE].low) {
8360 		auth_cfg->authentication_mode = cfg[CFG_AUTH_MODE].current;
8361 	} else if (auth_cfg->authentication_mode > cfg[CFG_AUTH_MODE].hi) {
8362 		auth_cfg->authentication_mode = cfg[CFG_AUTH_MODE].current;
8363 	}
8364 	/* Check bidirectional */
8365 	if (auth_cfg->bidirectional < cfg[CFG_AUTH_BIDIR].low) {
8366 		auth_cfg->bidirectional = cfg[CFG_AUTH_BIDIR].current;
8367 	} else if (auth_cfg->bidirectional > cfg[CFG_AUTH_BIDIR].hi) {
8368 		auth_cfg->bidirectional = cfg[CFG_AUTH_BIDIR].current;
8369 	}
8370 	/* Check authentication_type_priority and hash_priority */
8371 	for (i = 0; i < 4; i++) {
8372 		if (auth_cfg->authentication_type_priority[i] >
8373 		    DFC_AUTH_TYPE_MAX) {
8374 			/* Set to current default */
8375 			auth_cfg->authentication_type_priority[i] =
8376 			    hba->auth_cfg.authentication_type_priority[i];
8377 		}
8378 		if (auth_cfg->hash_priority[i] > DFC_AUTH_HASH_MAX) {
8379 			/* Set to current default */
8380 			auth_cfg->hash_priority[i] =
8381 			    hba->auth_cfg.hash_priority[i];
8382 		}
8383 	}
8384 
8385 	/* Check dh_group_priority */
8386 	for (i = 0; i < 8; i++) {
8387 		if (auth_cfg->dh_group_priority[i] > DFC_AUTH_GROUP_MAX) {
8388 			/* Set to current default */
8389 			auth_cfg->dh_group_priority[i] =
8390 			    hba->auth_cfg.dh_group_priority[i];
8391 		}
8392 	}
8393 
8394 	/* Check reauthenticate_time_interval */
8395 	if (auth_cfg->reauthenticate_time_interval <
8396 	    cfg[CFG_AUTH_INTERVAL].low) {
8397 		auth_cfg->reauthenticate_time_interval =
8398 		    cfg[CFG_AUTH_INTERVAL].current;
8399 	} else if (auth_cfg->reauthenticate_time_interval >
8400 	    cfg[CFG_AUTH_INTERVAL].hi) {
8401 		auth_cfg->reauthenticate_time_interval =
8402 		    cfg[CFG_AUTH_INTERVAL].current;
8403 	}
8404 	emlxs_auth_cfg_print(hba, auth_cfg);
8405 
8406 out:
8407 
8408 	if (errors) {
8409 		bzero(auth_cfg, sizeof (emlxs_auth_cfg_t));
8410 		return (0);
8411 	}
8412 	return (1);
8413 
8414 } /* emlxs_auth_cfg_parse() */
8415 
8416 
8417 /* **************************** AUTH KEY MANAGEMENT ************************* */
8418 
8419 /* auth_lock must be held */
8420 extern emlxs_auth_key_t *
emlxs_auth_key_find(emlxs_port_t * port,uint8_t * rwwpn)8421 emlxs_auth_key_find(emlxs_port_t *port, uint8_t *rwwpn)
8422 {
8423 	emlxs_hba_t *hba = HBA;
8424 	emlxs_auth_key_t *auth_key;
8425 
8426 	if (rwwpn) {
8427 		/* lwwpn, rwwpn */
8428 		auth_key = emlxs_auth_key_get(hba,
8429 		    (uint8_t *)&port->wwpn, (uint8_t *)rwwpn);
8430 
8431 		if (auth_key) {
8432 			emlxs_auth_key_print(hba, auth_key);
8433 			return (auth_key);
8434 		}
8435 		/* null, rwwpn */
8436 		auth_key = emlxs_auth_key_get(hba,
8437 		    (uint8_t *)emlxs_null_wwn, (uint8_t *)rwwpn);
8438 
8439 		if (auth_key) {
8440 			emlxs_auth_key_print(hba, auth_key);
8441 			return (auth_key);
8442 		}
8443 	}
8444 	/* lwwpn, null */
8445 	auth_key = emlxs_auth_key_get(hba,
8446 	    (uint8_t *)&port->wwpn, (uint8_t *)emlxs_null_wwn);
8447 
8448 	if (auth_key) {
8449 		emlxs_auth_key_print(hba, auth_key);
8450 		return (auth_key);
8451 	}
8452 	return (NULL);
8453 
8454 } /* emlxs_auth_key_find() */
8455 
8456 
8457 static void
emlxs_auth_key_init(emlxs_hba_t * hba)8458 emlxs_auth_key_init(emlxs_hba_t *hba)
8459 {
8460 	emlxs_auth_key_t *auth_key;
8461 
8462 	/* Destroy old table if one exists */
8463 	emlxs_auth_key_fini(hba);
8464 
8465 	mutex_enter(&hba->auth_lock);
8466 
8467 	/* Zero default entry */
8468 	auth_key = &hba->auth_key;
8469 	bzero(auth_key, sizeof (emlxs_auth_key_t));
8470 	auth_key->next = auth_key;
8471 	auth_key->prev = auth_key;
8472 
8473 	/* Configure the default entry */
8474 	auth_key->local_password_type = PASSWORD_TYPE_IGNORE;
8475 	auth_key->remote_password_type = PASSWORD_TYPE_IGNORE;
8476 
8477 	emlxs_auth_key_read(hba);
8478 
8479 	mutex_exit(&hba->auth_lock);
8480 
8481 	return;
8482 
8483 } /* emlxs_auth_key_init() */
8484 
8485 
8486 static void
emlxs_auth_key_fini(emlxs_hba_t * hba)8487 emlxs_auth_key_fini(emlxs_hba_t *hba)
8488 {
8489 	emlxs_auth_key_t *auth_key = hba->auth_key.next;
8490 	emlxs_auth_key_t *next;
8491 
8492 	mutex_enter(&hba->auth_lock);
8493 
8494 	while (auth_key && auth_key != &hba->auth_key) {
8495 		next = auth_key->next;
8496 		emlxs_auth_key_destroy(hba, auth_key);
8497 		auth_key = next;
8498 	}
8499 
8500 	mutex_exit(&hba->auth_lock);
8501 
8502 	return;
8503 
8504 } /* emlxs_auth_key_fini() */
8505 
8506 
8507 static void
emlxs_auth_key_print(emlxs_hba_t * hba,emlxs_auth_key_t * auth_key)8508 emlxs_auth_key_print(emlxs_hba_t *hba, emlxs_auth_key_t *auth_key)
8509 {
8510 	emlxs_port_t *port = &PPORT;
8511 	char s_lwwpn[32];
8512 	char s_rwwpn[32];
8513 
8514 	EMLXS_MSGF(EMLXS_CONTEXT,
8515 	    &emlxs_fcsp_detail_msg,
8516 	    "auth-key> %s:%s:%x:*%d chars*:%x:*%d chars*",
8517 	    emlxs_wwn_xlate(s_lwwpn, sizeof (s_lwwpn),
8518 	    (uint8_t *)&auth_key->local_entity),
8519 	    emlxs_wwn_xlate(s_rwwpn, sizeof (s_rwwpn),
8520 	    (uint8_t *)&auth_key->remote_entity),
8521 	    auth_key->local_password_type, auth_key->local_password_length,
8522 	    auth_key->remote_password_type, auth_key->remote_password_length);
8523 
8524 	return;
8525 
8526 } /* emlxs_auth_key_print() */
8527 
8528 
8529 /* auth_lock must be held */
8530 static emlxs_auth_key_t *
emlxs_auth_key_get(emlxs_hba_t * hba,uint8_t * lwwpn,uint8_t * rwwpn)8531 emlxs_auth_key_get(emlxs_hba_t *hba, uint8_t *lwwpn, uint8_t *rwwpn)
8532 {
8533 	emlxs_auth_key_t *auth_key;
8534 
8535 	if (!lwwpn || !rwwpn) {
8536 		return (NULL);
8537 	}
8538 	/* Check for default entry */
8539 	if ((bcmp(lwwpn, emlxs_null_wwn, 8) == 0) &&
8540 	    (bcmp(rwwpn, emlxs_null_wwn, 8) == 0)) {
8541 		return (&hba->auth_key);
8542 	}
8543 	for (auth_key = hba->auth_key.next; auth_key !=
8544 	    &hba->auth_key; auth_key = auth_key->next) {
8545 		/* Find pwd entry for this local port */
8546 
8547 		/* Check for exact wwpn match */
8548 		if (bcmp((void *)&auth_key->local_entity,
8549 		    (void *)lwwpn, 8) != 0) {
8550 			continue;
8551 		}
8552 		/* Find pwd entry for remote port */
8553 
8554 		/* Check for exact wwpn match */
8555 		if (bcmp((void *)&auth_key->remote_entity,
8556 		    (void *)rwwpn, 8) != 0) {
8557 			continue;
8558 		}
8559 		return (auth_key);
8560 	}
8561 
8562 	return (NULL);
8563 
8564 } /* emlxs_auth_key_get() */
8565 
8566 
8567 /* auth_lock must be held */
8568 static emlxs_auth_key_t *
emlxs_auth_key_create(emlxs_hba_t * hba,uint8_t * lwwpn,uint8_t * rwwpn)8569 emlxs_auth_key_create(emlxs_hba_t *hba, uint8_t *lwwpn, uint8_t *rwwpn)
8570 {
8571 	emlxs_auth_key_t *auth_key;
8572 
8573 	/* First check if entry already exists */
8574 	auth_key = emlxs_auth_key_get(hba, lwwpn, rwwpn);
8575 
8576 	if (auth_key) {
8577 		return (auth_key);
8578 	}
8579 	/* Allocate entry */
8580 	auth_key = (emlxs_auth_key_t *)kmem_zalloc(sizeof (emlxs_auth_key_t),
8581 	    KM_NOSLEEP);
8582 
8583 	if (!auth_key) {
8584 		return (NULL);
8585 	}
8586 	/* Initialize name pair */
8587 	if (lwwpn) {
8588 		bcopy((void *)lwwpn, (void *)&auth_key->local_entity, 8);
8589 	}
8590 	if (rwwpn) {
8591 		bcopy((void *)rwwpn, (void *)&auth_key->remote_entity, 8);
8592 	}
8593 	/* Initialize type */
8594 	auth_key->local_password_type = PASSWORD_TYPE_IGNORE;
8595 	auth_key->remote_password_type = PASSWORD_TYPE_IGNORE;
8596 
8597 	/* Add to list */
8598 	auth_key->next = &hba->auth_key;
8599 	auth_key->prev = hba->auth_key.prev;
8600 	hba->auth_key.prev->next = auth_key;
8601 	hba->auth_key.prev = auth_key;
8602 	hba->auth_key_count++;
8603 
8604 	return (auth_key);
8605 
8606 } /* emlxs_auth_key_create() */
8607 
8608 
8609 /* auth_lock must be held */
8610 static void
emlxs_auth_key_destroy(emlxs_hba_t * hba,emlxs_auth_key_t * auth_key)8611 emlxs_auth_key_destroy(emlxs_hba_t *hba, emlxs_auth_key_t *auth_key)
8612 {
8613 
8614 	if (!auth_key) {
8615 		return;
8616 	}
8617 	if (auth_key == &hba->auth_key) {
8618 		return;
8619 	}
8620 	/* Remove from  list */
8621 	auth_key->next->prev = auth_key->prev;
8622 	auth_key->prev->next = auth_key->next;
8623 	hba->auth_key_count--;
8624 
8625 	/* Remove node binding */
8626 	if (auth_key->node &&
8627 	    auth_key->node->nlp_active &&
8628 	    (auth_key->node->node_dhc.parent_auth_key == auth_key)) {
8629 		auth_key->node->node_dhc.parent_auth_key = NULL;
8630 	}
8631 	bzero(auth_key, sizeof (emlxs_auth_key_t));
8632 	kmem_free(auth_key, sizeof (emlxs_auth_key_t));
8633 
8634 	return;
8635 
8636 } /* emlxs_auth_key_destroy() */
8637 
8638 
8639 /* auth_lock must be held */
8640 static void
emlxs_auth_key_read(emlxs_hba_t * hba)8641 emlxs_auth_key_read(emlxs_hba_t *hba)
8642 {
8643 	emlxs_port_t *port = &PPORT;
8644 	char **arrayp;
8645 	emlxs_auth_key_t auth_key;
8646 	emlxs_auth_key_t *auth_key2;
8647 	uint32_t cnt;
8648 	uint32_t rval;
8649 	char buffer[64];
8650 	char *prop_str;
8651 	uint32_t i;
8652 
8653 	/* Check for the per adapter setting */
8654 	(void) snprintf(buffer, sizeof (buffer), "%s%d-auth-keys", DRIVER_NAME,
8655 	    hba->ddiinst);
8656 	cnt = 0;
8657 	arrayp = NULL;
8658 	rval = ddi_prop_lookup_string_array(DDI_DEV_T_ANY, hba->dip,
8659 	    (DDI_PROP_DONTPASS),
8660 	    buffer, &arrayp, &cnt);
8661 
8662 	if ((rval != DDI_PROP_SUCCESS) || !cnt || !arrayp) {
8663 		/* Check for the global setting */
8664 		cnt = 0;
8665 		arrayp = NULL;
8666 		rval = ddi_prop_lookup_string_array(DDI_DEV_T_ANY, hba->dip,
8667 		    (DDI_PROP_DONTPASS),
8668 		    "auth-keys", &arrayp, &cnt);
8669 	}
8670 	if ((rval != DDI_PROP_SUCCESS) || !cnt || !arrayp) {
8671 		return;
8672 	}
8673 	for (i = 0; i < cnt; i++) {
8674 		prop_str = arrayp[i];
8675 		if (prop_str == NULL) {
8676 			break;
8677 		}
8678 		/* parse the string */
8679 		if (emlxs_auth_key_parse(hba, &auth_key, prop_str) == 0) {
8680 			EMLXS_MSGF(EMLXS_CONTEXT,
8681 			    &emlxs_attach_msg,
8682 			    "Error parsing auth_keys property. entry=%d", i);
8683 			continue;
8684 		}
8685 		auth_key2 = emlxs_auth_key_create(hba,
8686 		    (uint8_t *)&auth_key.local_entity,
8687 		    (uint8_t *)&auth_key.remote_entity);
8688 
8689 		if (!auth_key2) {
8690 			EMLXS_MSGF(EMLXS_CONTEXT,
8691 			    &emlxs_attach_msg,
8692 			    "Out of memory parsing auth_keys property. %d",
8693 			    i);
8694 			return;
8695 		}
8696 		auth_key.next = auth_key2->next;
8697 		auth_key.prev = auth_key2->prev;
8698 		bcopy((uint8_t *)&auth_key,
8699 		    (uint8_t *)auth_key2, sizeof (emlxs_auth_key_t));
8700 	}
8701 
8702 	return;
8703 
8704 } /* emlxs_auth_key_read() */
8705 
8706 
8707 /* auth_lock must be held */
8708 static uint32_t
emlxs_auth_key_parse(emlxs_hba_t * hba,emlxs_auth_key_t * auth_key,char * prop_str)8709 emlxs_auth_key_parse(
8710 	emlxs_hba_t *hba,
8711 	emlxs_auth_key_t *auth_key,
8712 	char *prop_str)
8713 {
8714 	emlxs_port_t *port = &PPORT;
8715 	uint32_t errors = 0;
8716 	uint32_t c1;
8717 	uint8_t *np;
8718 	uint32_t j;
8719 	uint32_t sum;
8720 	char *s;
8721 
8722 	s = prop_str;
8723 	bzero(auth_key, sizeof (emlxs_auth_key_t));
8724 
8725 	/* Read local wwpn */
8726 	np = (uint8_t *)&auth_key->local_entity;
8727 	for (j = 0; j < 8; j++) {
8728 		c1 = *s++;
8729 		if ((c1 >= '0') && (c1 <= '9')) {
8730 			sum = ((c1 - '0') << 4);
8731 		} else if ((c1 >= 'a') && (c1 <= 'f')) {
8732 			sum = ((c1 - 'a' + 10) << 4);
8733 		} else if ((c1 >= 'A') && (c1 <= 'F')) {
8734 			sum = ((c1 - 'A' + 10) << 4);
8735 		} else {
8736 			EMLXS_MSGF(EMLXS_CONTEXT,
8737 			    &emlxs_attach_debug_msg,
8738 			    "Cfg err: Invalid LWWPN found. %d %c",
8739 			    j, c1);
8740 			errors++;
8741 		}
8742 
8743 		c1 = *s++;
8744 		if ((c1 >= '0') && (c1 <= '9')) {
8745 			sum |= (c1 - '0');
8746 		} else if ((c1 >= 'a') && (c1 <= 'f')) {
8747 			sum |= (c1 - 'a' + 10);
8748 		} else if ((c1 >= 'A') && (c1 <= 'F')) {
8749 			sum |= (c1 - 'A' + 10);
8750 		} else {
8751 			EMLXS_MSGF(EMLXS_CONTEXT,
8752 			    &emlxs_attach_debug_msg,
8753 			    "Cfg err: Invalid LWWPN found. %d %c",
8754 			    j, c1);
8755 			errors++;
8756 		}
8757 
8758 		*np++ = (uint8_t)sum;
8759 	}
8760 
8761 	if (*s++ != ':') {
8762 		EMLXS_MSGF(EMLXS_CONTEXT,
8763 		    &emlxs_attach_debug_msg,
8764 		    "Cfg err: Invalid delimiter after LWWPN.");
8765 		goto out;
8766 	}
8767 	/* Read remote wwpn */
8768 	np = (uint8_t *)&auth_key->remote_entity;
8769 	for (j = 0; j < 8; j++) {
8770 		c1 = *s++;
8771 		if ((c1 >= '0') && (c1 <= '9')) {
8772 			sum = ((c1 - '0') << 4);
8773 		} else if ((c1 >= 'a') && (c1 <= 'f')) {
8774 			sum = ((c1 - 'a' + 10) << 4);
8775 		} else if ((c1 >= 'A') && (c1 <= 'F')) {
8776 			sum = ((c1 - 'A' + 10) << 4);
8777 		} else {
8778 			EMLXS_MSGF(EMLXS_CONTEXT,
8779 			    &emlxs_attach_debug_msg,
8780 			    "Cfg err: Invalid RWWPN found.%d %c",
8781 			    j, c1);
8782 			errors++;
8783 		}
8784 
8785 		c1 = *s++;
8786 		if ((c1 >= '0') && (c1 <= '9')) {
8787 			sum |= (c1 - '0');
8788 		} else if ((c1 >= 'a') && (c1 <= 'f')) {
8789 			sum |= (c1 - 'a' + 10);
8790 		} else if ((c1 >= 'A') && (c1 <= 'F')) {
8791 			sum |= (c1 - 'A' + 10);
8792 		} else {
8793 			EMLXS_MSGF(EMLXS_CONTEXT,
8794 			    &emlxs_attach_debug_msg,
8795 			    "Cfg err: Invalid RWWPN found. %d %c",
8796 			    j, c1);
8797 			errors++;
8798 		}
8799 
8800 		*np++ = (uint8_t)sum;
8801 	}
8802 
8803 	if (*s++ != ':') {
8804 		EMLXS_MSGF(EMLXS_CONTEXT,
8805 		    &emlxs_attach_debug_msg,
8806 		    "Cfg err: Invalid delimiter after RWWPN.");
8807 		goto out;
8808 	}
8809 	/* Read lpwd type (%x) */
8810 	sum = 0;
8811 	do {
8812 		c1 = *s++;
8813 		if ((c1 >= '0') && (c1 <= '9')) {
8814 			sum = (sum << 4) + (c1 - '0');
8815 		} else if ((c1 >= 'a') && (c1 <= 'f')) {
8816 			sum = (sum << 4) + (c1 - 'a' + 10);
8817 		} else if ((c1 >= 'A') && (c1 <= 'F')) {
8818 			sum = (sum << 4) + (c1 - 'A' + 10);
8819 		} else {
8820 			EMLXS_MSGF(EMLXS_CONTEXT,
8821 			    &emlxs_attach_debug_msg,
8822 			    "Cfg err: Invalid lpwd type found. %c %d",
8823 			    c1, sum);
8824 
8825 			errors++;
8826 		}
8827 
8828 	} while (*s != ':' && *s != 0);
8829 	auth_key->local_password_type = (uint16_t)sum;
8830 
8831 	if (*s++ != ':') {
8832 		EMLXS_MSGF(EMLXS_CONTEXT,
8833 		    &emlxs_attach_debug_msg,
8834 		    "Cfg err: Invalid delimiter after lpwd type.");
8835 		goto out;
8836 	}
8837 	/* Read lpwd */
8838 	np = (uint8_t *)&auth_key->local_password;
8839 	j = 0;
8840 	switch (auth_key->local_password_type) {
8841 	case 1:	/* ACSII */
8842 		while (*s != ':' && *s != 0) {
8843 			*np++ = *s++;
8844 			j++;
8845 		}
8846 		break;
8847 
8848 	case 2:	/* Hex */
8849 		do {
8850 			c1 = *s++;
8851 			if ((c1 >= '0') && (c1 <= '9')) {
8852 				sum = ((c1 - '0') << 4);
8853 			} else if ((c1 >= 'a') && (c1 <= 'f')) {
8854 				sum = ((c1 - 'a' + 10) << 4);
8855 			} else if ((c1 >= 'A') && (c1 <= 'F')) {
8856 				sum = ((c1 - 'A' + 10) << 4);
8857 			} else {
8858 			EMLXS_MSGF(EMLXS_CONTEXT,
8859 			    &emlxs_attach_debug_msg,
8860 			    "Cfg err: Invalid lpwd found. %d %c",
8861 			    j, c1);
8862 				errors++;
8863 			}
8864 
8865 			c1 = *s++;
8866 			if ((c1 >= '0') && (c1 <= '9')) {
8867 				sum |= (c1 - '0');
8868 			} else if ((c1 >= 'a') && (c1 <= 'f')) {
8869 				sum |= (c1 - 'a' + 10);
8870 			} else if ((c1 >= 'A') && (c1 <= 'F')) {
8871 				sum |= (c1 - 'A' + 10);
8872 			} else {
8873 			EMLXS_MSGF(EMLXS_CONTEXT,
8874 			    &emlxs_attach_debug_msg,
8875 			    "Cfg err: Invalid lpwd found. %d %c",
8876 			    j, c1);
8877 				errors++;
8878 			}
8879 
8880 			*np++ = (uint8_t)sum;
8881 			j++;
8882 
8883 		} while (*s != ':' && *s != 0);
8884 
8885 		break;
8886 
8887 	case 0:	/* Ignore */
8888 	case 3:	/* Ignore */
8889 		break;
8890 
8891 	default:
8892 		EMLXS_MSGF(EMLXS_CONTEXT,
8893 		    &emlxs_attach_debug_msg,
8894 		    "Config error: Invalid lpwd type found. type=%x",
8895 		    auth_key->local_password_type);
8896 
8897 		errors++;
8898 		goto out;
8899 	}
8900 	auth_key->local_password_length = (uint16_t)j;
8901 
8902 	if (*s++ != ':') {
8903 		EMLXS_MSGF(EMLXS_CONTEXT,
8904 		    &emlxs_attach_debug_msg,
8905 		    "Config error: Invalid delimiter after lpwd.");
8906 		goto out;
8907 	}
8908 	/* Read rpwd type (%x) */
8909 	sum = 0;
8910 	do {
8911 		c1 = *s++;
8912 		if ((c1 >= '0') && (c1 <= '9')) {
8913 			sum = (sum << 4) + (c1 - '0');
8914 		} else if ((c1 >= 'a') && (c1 <= 'f')) {
8915 			sum = (sum << 4) + (c1 - 'a' + 10);
8916 		} else if ((c1 >= 'A') && (c1 <= 'F')) {
8917 			sum = (sum << 4) + (c1 - 'A' + 10);
8918 		} else {
8919 			EMLXS_MSGF(EMLXS_CONTEXT,
8920 			    &emlxs_attach_debug_msg,
8921 			    "Config error: Invalid rpwd type found. %c %d",
8922 			    c1, sum);
8923 
8924 			errors++;
8925 		}
8926 
8927 	} while (*s != ':' && *s != 0);
8928 	auth_key->remote_password_type = (uint16_t)sum;
8929 
8930 	if (*s++ != ':') {
8931 		EMLXS_MSGF(EMLXS_CONTEXT,
8932 		    &emlxs_attach_debug_msg,
8933 		    "Config error: Invalid delimiter after rpwd type.");
8934 		goto out;
8935 	}
8936 	/* Read rpwd */
8937 	np = (uint8_t *)&auth_key->remote_password;
8938 	j = 0;
8939 	switch (auth_key->remote_password_type) {
8940 	case 1:	/* ACSII */
8941 		while (*s != ':' && *s != 0) {
8942 			*np++ = *s++;
8943 			j++;
8944 		}
8945 		break;
8946 
8947 	case 2:	/* Hex */
8948 		do {
8949 			c1 = *s++;
8950 			if ((c1 >= '0') && (c1 <= '9')) {
8951 				sum = ((c1 - '0') << 4);
8952 			} else if ((c1 >= 'a') && (c1 <= 'f')) {
8953 				sum = ((c1 - 'a' + 10) << 4);
8954 			} else if ((c1 >= 'A') && (c1 <= 'F')) {
8955 				sum = ((c1 - 'A' + 10) << 4);
8956 			} else {
8957 			EMLXS_MSGF(EMLXS_CONTEXT,
8958 			    &emlxs_attach_debug_msg,
8959 			    "Cfg err: Invalid rpwd found. %d %c",
8960 			    j, c1);
8961 				errors++;
8962 			}
8963 
8964 			c1 = *s++;
8965 			if ((c1 >= '0') && (c1 <= '9')) {
8966 				sum |= (c1 - '0');
8967 			} else if ((c1 >= 'a') && (c1 <= 'f')) {
8968 				sum |= (c1 - 'a' + 10);
8969 			} else if ((c1 >= 'A') && (c1 <= 'F')) {
8970 				sum |= (c1 - 'A' + 10);
8971 			} else {
8972 			EMLXS_MSGF(EMLXS_CONTEXT,
8973 			    &emlxs_attach_debug_msg,
8974 			    "Cfg err: Invalid rpwd found. %d %c",
8975 			    j, c1);
8976 				errors++;
8977 			}
8978 
8979 			*np++ = (uint8_t)sum;
8980 			j++;
8981 
8982 		} while (*s != ':' && *s != 0);
8983 
8984 		break;
8985 
8986 	case 0:	/* Ignore */
8987 	case 3:	/* Ignore */
8988 		break;
8989 
8990 	default:
8991 		EMLXS_MSGF(EMLXS_CONTEXT,
8992 		    &emlxs_attach_debug_msg,
8993 		    "Cfg error: Invalid rpwd type found. type=%x",
8994 		    auth_key->remote_password_type);
8995 
8996 		errors++;
8997 		goto out;
8998 	}
8999 	auth_key->remote_password_length = (uint16_t)j;
9000 
9001 	if (errors) {
9002 		goto out;
9003 	}
9004 	/* Verify values */
9005 	if (auth_key->local_password_type == 0 ||
9006 	    auth_key->local_password_type > 3 ||
9007 	    auth_key->local_password_length == 0) {
9008 
9009 		auth_key->local_password_type = 3;
9010 		auth_key->local_password_length = 0;
9011 		bzero(auth_key->local_password,
9012 		    sizeof (auth_key->local_password));
9013 	}
9014 	if (auth_key->remote_password_type == 0 ||
9015 	    auth_key->remote_password_type > 3 ||
9016 	    auth_key->remote_password_length == 0) {
9017 
9018 		auth_key->remote_password_type = 3;
9019 		auth_key->remote_password_length = 0;
9020 		bzero(auth_key->remote_password,
9021 		    sizeof (auth_key->remote_password));
9022 	}
9023 	/* Display entry */
9024 	emlxs_auth_key_print(hba, auth_key);
9025 
9026 out:
9027 	if (errors) {
9028 		bzero(auth_key, sizeof (emlxs_auth_key_t));
9029 		return (0);
9030 	}
9031 	return (1);
9032 
9033 } /* emlxs_auth_key_parse() */
9034 
9035 
9036 /* ************************** AUTH DFCLIB SUPPORT *********************** */
9037 
9038 /* Provides DFC support for emlxs_dfc_init_auth() */
9039 extern uint32_t
emlxs_dhc_init_auth(emlxs_hba_t * hba,uint8_t * lwwpn,uint8_t * rwwpn)9040 emlxs_dhc_init_auth(emlxs_hba_t *hba, uint8_t *lwwpn, uint8_t *rwwpn)
9041 {
9042 	emlxs_port_t *port = &PPORT;
9043 	emlxs_config_t *cfg = &CFG;
9044 	NODELIST *ndlp;
9045 	uint32_t vpi;
9046 	char s_wwpn[64];
9047 
9048 	/* Return is authentication is not enabled */
9049 	if (cfg[CFG_AUTH_ENABLE].current == 0) {
9050 		EMLXS_MSGF(EMLXS_CONTEXT,
9051 		    &emlxs_fcsp_debug_msg,
9052 		    "dhc_init_auth. Auth disabled.");
9053 
9054 		return (DFC_AUTH_AUTHENTICATION_DISABLED);
9055 	}
9056 	/* Scan for lwwpn match */
9057 	for (vpi = 0; vpi < MAX_VPORTS; vpi++) {
9058 		port = &VPORT(vpi);
9059 
9060 		if (!(port->flag & EMLXS_PORT_BOUND)) {
9061 			continue;
9062 		}
9063 		if (bcmp((uint8_t *)&port->wwpn, lwwpn, 8) == 0) {
9064 			break;
9065 		}
9066 	}
9067 
9068 	if (vpi == MAX_VPORTS) {
9069 		EMLXS_MSGF(EMLXS_CONTEXT,
9070 		    &emlxs_dfc_error_msg,
9071 		    "dhc_init_auth: lwwpn not found. %s",
9072 		    emlxs_wwn_xlate(s_wwpn, sizeof (s_wwpn), lwwpn));
9073 
9074 		return (DFC_AUTH_WWN_NOT_FOUND);
9075 	}
9076 	if (bcmp(rwwpn, emlxs_fabric_wwn, 8) == 0) {
9077 		/* Scan for fabric node */
9078 		if ((ndlp = emlxs_node_find_did(port, FABRIC_DID, 1)) == NULL) {
9079 			EMLXS_MSGF(EMLXS_CONTEXT,
9080 			    &emlxs_dfc_error_msg,
9081 			    "dhc_init_auth: fabric node not found.");
9082 
9083 			return (DFC_AUTH_WWN_NOT_FOUND);
9084 		}
9085 	} else {
9086 		/* Scan for rwwpn match */
9087 		if ((ndlp = emlxs_node_find_wwpn(port, rwwpn, 1)) == NULL) {
9088 			EMLXS_MSGF(EMLXS_CONTEXT,
9089 			    &emlxs_dfc_error_msg,
9090 			    "dhc_init_auth: rwwpn not found. %s",
9091 			    emlxs_wwn_xlate(s_wwpn, sizeof (s_wwpn), rwwpn));
9092 
9093 			return (DFC_AUTH_WWN_NOT_FOUND);
9094 		}
9095 	}
9096 
9097 	if ((ndlp->nlp_DID != FABRIC_DID) &&
9098 	    ((port->port_dhc.state != ELX_FABRIC_AUTH_SUCCESS))) {
9099 		return (DFC_IO_ERROR);
9100 	}
9101 	if (ndlp->node_dhc.state >= NODE_STATE_AUTH_NEGOTIATE_ISSUE) {
9102 		return (DFC_AUTH_AUTHENTICATION_GOINGON);
9103 	}
9104 	if (ndlp->node_dhc.state == NODE_STATE_AUTH_SUCCESS) {
9105 		ndlp->node_dhc.nlp_reauth_status = NLP_HOST_REAUTH_IN_PROGRESS;
9106 	}
9107 	/* Attempt to start authentication */
9108 	if (emlxs_dhc_auth_start(port, ndlp, NULL, NULL) != 0) {
9109 		return (DFC_IO_ERROR);
9110 	}
9111 	return (0);
9112 
9113 } /* emlxs_dhc_init_auth() */
9114 
9115 
9116 /* Provides DFC support for emlxs_dfc_get_auth_cfg() */
9117 extern uint32_t
emlxs_dhc_get_auth_cfg(emlxs_hba_t * hba,dfc_fcsp_config_t * fcsp_cfg)9118 emlxs_dhc_get_auth_cfg(emlxs_hba_t *hba, dfc_fcsp_config_t *fcsp_cfg)
9119 {
9120 	emlxs_port_t *port = &PPORT;
9121 	emlxs_config_t *cfg = &CFG;
9122 	char s_lwwpn[64];
9123 	char s_rwwpn[64];
9124 	emlxs_auth_cfg_t *auth_cfg;
9125 	uint32_t i;
9126 
9127 	/* Return is authentication is not enabled */
9128 	if (cfg[CFG_AUTH_ENABLE].current == 0) {
9129 		EMLXS_MSGF(EMLXS_CONTEXT,
9130 		    &emlxs_fcsp_debug_msg,
9131 		    "dhc_get_auth_cfg. Auth disabled.");
9132 
9133 		return (DFC_AUTH_AUTHENTICATION_DISABLED);
9134 	}
9135 	mutex_enter(&hba->auth_lock);
9136 
9137 	auth_cfg = emlxs_auth_cfg_get(hba,
9138 	    (uint8_t *)&fcsp_cfg->lwwpn, (uint8_t *)&fcsp_cfg->rwwpn);
9139 
9140 	if (!auth_cfg) {
9141 		EMLXS_MSGF(EMLXS_CONTEXT,
9142 		    &emlxs_dfc_error_msg,
9143 		    "dhc_get_auth_cfg: entry not found. %s:%s",
9144 		    emlxs_wwn_xlate(s_lwwpn, sizeof (s_lwwpn),
9145 		    (uint8_t *)&fcsp_cfg->lwwpn),
9146 		    emlxs_wwn_xlate(s_rwwpn, sizeof (s_rwwpn),
9147 		    (uint8_t *)&fcsp_cfg->rwwpn));
9148 
9149 		mutex_exit(&hba->auth_lock);
9150 
9151 		return (DFC_AUTH_NOT_CONFIGURED);
9152 	}
9153 	fcsp_cfg->auth_tov = auth_cfg->authentication_timeout;
9154 	fcsp_cfg->auth_mode = auth_cfg->authentication_mode;
9155 	fcsp_cfg->auth_bidir = auth_cfg->bidirectional;
9156 
9157 	for (i = 0; i < 4; i++) {
9158 		fcsp_cfg->type_priority[i] =
9159 		    auth_cfg->authentication_type_priority[i];
9160 		fcsp_cfg->hash_priority[i] =
9161 		    auth_cfg->hash_priority[i];
9162 	}
9163 
9164 	for (i = 0; i < 8; i++) {
9165 		fcsp_cfg->group_priority[i] = auth_cfg->dh_group_priority[i];
9166 	}
9167 
9168 	fcsp_cfg->reauth_tov = auth_cfg->reauthenticate_time_interval;
9169 
9170 	mutex_exit(&hba->auth_lock);
9171 
9172 	return (0);
9173 
9174 } /* emlxs_dhc_get_auth_cfg() */
9175 
9176 
9177 /* Provides DFC support for emlxs_dfc_set_auth_cfg() */
9178 extern uint32_t
emlxs_dhc_add_auth_cfg(emlxs_hba_t * hba,dfc_fcsp_config_t * fcsp_cfg,dfc_password_t * dfc_pwd)9179 emlxs_dhc_add_auth_cfg(
9180 	emlxs_hba_t *hba,
9181 	dfc_fcsp_config_t *fcsp_cfg,
9182 	dfc_password_t *dfc_pwd)
9183 {
9184 	emlxs_port_t *port = &PPORT;
9185 	emlxs_config_t *cfg = &CFG;
9186 	emlxs_auth_cfg_t *auth_cfg;
9187 	emlxs_auth_key_t *auth_key;
9188 	uint32_t i;
9189 	NODELIST *ndlp;
9190 
9191 	/* Return if authentication is not enabled */
9192 	if (cfg[CFG_AUTH_ENABLE].current == 0) {
9193 		EMLXS_MSGF(EMLXS_CONTEXT,
9194 		    &emlxs_fcsp_debug_msg,
9195 		    "dhc_add_auth_cfg. Auth disabled.");
9196 
9197 		return (DFC_AUTH_AUTHENTICATION_DISABLED);
9198 	}
9199 	mutex_enter(&hba->auth_lock);
9200 
9201 	auth_key = emlxs_auth_key_get(hba,
9202 	    (uint8_t *)&fcsp_cfg->lwwpn, (uint8_t *)&fcsp_cfg->rwwpn);
9203 
9204 	if (auth_key &&
9205 	    (auth_key->local_password_type == PASSWORD_TYPE_ASCII ||
9206 	    auth_key->local_password_type == PASSWORD_TYPE_BINARY)) {
9207 
9208 		/* Verify local password */
9209 		if ((auth_key->local_password_length != dfc_pwd->length) ||
9210 		    (auth_key->local_password_type != dfc_pwd->type) ||
9211 		    bcmp(dfc_pwd->password, auth_key->local_password,
9212 		    dfc_pwd->length)) {
9213 			EMLXS_MSGF(EMLXS_CONTEXT,
9214 			    &emlxs_dfc_error_msg,
9215 			    "dhc_add_auth_cfg: Invalid local password.");
9216 
9217 			mutex_exit(&hba->auth_lock);
9218 
9219 			return (DFC_AUTH_COMPARE_FAILED);
9220 		}
9221 	}
9222 	/* Create entry */
9223 	auth_cfg = emlxs_auth_cfg_create(hba,
9224 	    (uint8_t *)&fcsp_cfg->lwwpn,
9225 	    (uint8_t *)&fcsp_cfg->rwwpn);
9226 
9227 	if (!auth_cfg) {
9228 		EMLXS_MSGF(EMLXS_CONTEXT,
9229 		    &emlxs_dfc_error_msg,
9230 		    "dhc_add_auth_cfg: Out of memory.");
9231 
9232 		mutex_exit(&hba->auth_lock);
9233 
9234 		return (DFC_SYSRES_ERROR);
9235 	}
9236 	/* Init entry */
9237 	auth_cfg->authentication_timeout = fcsp_cfg->auth_tov;
9238 	auth_cfg->authentication_mode = fcsp_cfg->auth_mode;
9239 	auth_cfg->bidirectional = fcsp_cfg->auth_bidir;
9240 
9241 	for (i = 0; i < 4; i++) {
9242 		auth_cfg->authentication_type_priority[i] =
9243 		    fcsp_cfg->type_priority[i];
9244 		auth_cfg->hash_priority[i] =
9245 		    fcsp_cfg->hash_priority[i];
9246 	}
9247 
9248 	for (i = 0; i < 8; i++) {
9249 		auth_cfg->dh_group_priority[i] = fcsp_cfg->group_priority[i];
9250 	}
9251 
9252 	auth_cfg->reauthenticate_time_interval = fcsp_cfg->reauth_tov;
9253 
9254 	emlxs_auth_cfg_print(hba, auth_cfg);
9255 
9256 	/* Cancel old reauth to restart the new one if necessary */
9257 
9258 	/* Scan for lwwpn match */
9259 	for (i = 0; i < MAX_VPORTS; i++) {
9260 		port = &VPORT(i);
9261 
9262 		if (!(port->flag & EMLXS_PORT_BOUND)) {
9263 			continue;
9264 		}
9265 		if (bcmp((uint8_t *)&fcsp_cfg->lwwpn,
9266 		    (uint8_t *)&port->wwpn, 8)) {
9267 			continue;
9268 		}
9269 		/* Port match found */
9270 
9271 		if (bcmp((uint8_t *)&fcsp_cfg->rwwpn,
9272 		    emlxs_fabric_wwn, 8) == 0) {
9273 			/* Scan for fabric node */
9274 			if ((ndlp = emlxs_node_find_did(port,
9275 			    FABRIC_DID, 1)) == NULL) {
9276 				break;
9277 			}
9278 		} else {
9279 			/* Scan for rwwpn match */
9280 			if ((ndlp = emlxs_node_find_wwpn(port,
9281 			    (uint8_t *)&fcsp_cfg->rwwpn, 1)) == NULL) {
9282 				break;
9283 			}
9284 		}
9285 
9286 		emlxs_dhc_set_reauth_time(port, ndlp, ENABLE);
9287 
9288 		break;
9289 	}
9290 
9291 	mutex_exit(&hba->auth_lock);
9292 
9293 	return (0);
9294 
9295 } /* emlxs_dhc_add_auth_cfg() */
9296 
9297 
9298 /* Provides DFC support for emlxs_dfc_set_auth_cfg() */
9299 extern uint32_t
emlxs_dhc_delete_auth_cfg(emlxs_hba_t * hba,dfc_fcsp_config_t * fcsp_cfg,dfc_password_t * dfc_pwd)9300 emlxs_dhc_delete_auth_cfg(
9301 	emlxs_hba_t *hba,
9302 	dfc_fcsp_config_t *fcsp_cfg,
9303 	dfc_password_t *dfc_pwd)
9304 {
9305 	emlxs_port_t *port = &PPORT;
9306 	emlxs_config_t *cfg = &CFG;
9307 	char s_lwwpn[64];
9308 	char s_rwwpn[64];
9309 	emlxs_auth_key_t *auth_key;
9310 	emlxs_auth_cfg_t *auth_cfg;
9311 
9312 	/* Return is authentication is not enabled */
9313 	if (cfg[CFG_AUTH_ENABLE].current == 0) {
9314 		EMLXS_MSGF(EMLXS_CONTEXT,
9315 		    &emlxs_fcsp_debug_msg,
9316 		    "dhc_delete_auth_cfg. Auth disabled.");
9317 
9318 		return (DFC_AUTH_AUTHENTICATION_DISABLED);
9319 	}
9320 	mutex_enter(&hba->auth_lock);
9321 
9322 	auth_key = emlxs_auth_key_get(hba,
9323 	    (uint8_t *)&fcsp_cfg->lwwpn,
9324 	    (uint8_t *)&fcsp_cfg->rwwpn);
9325 
9326 	if (auth_key &&
9327 	    (auth_key->local_password_type == PASSWORD_TYPE_ASCII ||
9328 	    auth_key->local_password_type ==
9329 	    PASSWORD_TYPE_BINARY)) {
9330 		/* Verify local password */
9331 		if ((auth_key->local_password_length != dfc_pwd->length) ||
9332 		    (auth_key->local_password_type != dfc_pwd->type) ||
9333 		    bcmp(dfc_pwd->password,
9334 		    auth_key->local_password,
9335 		    dfc_pwd->length)) {
9336 
9337 			EMLXS_MSGF(EMLXS_CONTEXT,
9338 			    &emlxs_dfc_error_msg,
9339 			    "dhc_delete_auth_cfg: Ivld local pwd.");
9340 
9341 			mutex_exit(&hba->auth_lock);
9342 
9343 			return (DFC_AUTH_COMPARE_FAILED);
9344 		}
9345 	}
9346 	auth_cfg = emlxs_auth_cfg_get(hba,
9347 	    (uint8_t *)&fcsp_cfg->lwwpn, (uint8_t *)&fcsp_cfg->rwwpn);
9348 
9349 	if (!auth_cfg) {
9350 		EMLXS_MSGF(EMLXS_CONTEXT,
9351 		    &emlxs_dfc_error_msg,
9352 		    "dhc_delete_auth_cfg: entry not found. %s:%s",
9353 		    emlxs_wwn_xlate(s_lwwpn, sizeof (s_lwwpn),
9354 		    (uint8_t *)&fcsp_cfg->lwwpn),
9355 		    emlxs_wwn_xlate(s_rwwpn, sizeof (s_rwwpn),
9356 		    (uint8_t *)&fcsp_cfg->rwwpn));
9357 
9358 		mutex_exit(&hba->auth_lock);
9359 
9360 		return (DFC_AUTH_WWN_NOT_FOUND);
9361 	}
9362 	/* Destroy cfg entry */
9363 	emlxs_auth_cfg_destroy(hba, auth_cfg);
9364 
9365 	/* Destroy pwd entry */
9366 	emlxs_auth_key_destroy(hba, auth_key);
9367 
9368 	mutex_exit(&hba->auth_lock);
9369 
9370 	return (0);
9371 
9372 } /* emlxs_dhc_delete_auth_cfg() */
9373 
9374 
9375 /* Provides DFC support for emlxs_dfc_get_auth_key() */
9376 extern uint32_t
emlxs_dhc_get_auth_key(emlxs_hba_t * hba,dfc_auth_password_t * dfc_auth_pwd)9377 emlxs_dhc_get_auth_key(emlxs_hba_t *hba, dfc_auth_password_t *dfc_auth_pwd)
9378 {
9379 	emlxs_port_t *port = &PPORT;
9380 	emlxs_config_t *cfg = &CFG;
9381 	char s_lwwpn[64];
9382 	char s_rwwpn[64];
9383 	emlxs_auth_key_t *auth_key;
9384 
9385 	/* Return is authentication is not enabled */
9386 	if (cfg[CFG_AUTH_ENABLE].current == 0) {
9387 		EMLXS_MSGF(EMLXS_CONTEXT,
9388 		    &emlxs_fcsp_debug_msg,
9389 		    "dhc_get_auth_key. Auth disabled.");
9390 
9391 		return (DFC_AUTH_AUTHENTICATION_DISABLED);
9392 	}
9393 	mutex_enter(&hba->auth_lock);
9394 
9395 	auth_key = emlxs_auth_key_get(hba,
9396 	    (uint8_t *)&dfc_auth_pwd->lwwpn,
9397 	    (uint8_t *)&dfc_auth_pwd->rwwpn);
9398 
9399 	if (!auth_key) {
9400 		EMLXS_MSGF(EMLXS_CONTEXT,
9401 		    &emlxs_dfc_error_msg,
9402 		    "dhc_get_auth_key: entry not found. %s:%s",
9403 		    emlxs_wwn_xlate(s_lwwpn, sizeof (s_lwwpn),
9404 		    (uint8_t *)&dfc_auth_pwd->lwwpn),
9405 		    emlxs_wwn_xlate(s_rwwpn, sizeof (s_rwwpn),
9406 		    (uint8_t *)&dfc_auth_pwd->rwwpn));
9407 
9408 		mutex_exit(&hba->auth_lock);
9409 
9410 		return (DFC_AUTH_NOT_CONFIGURED);
9411 	}
9412 	dfc_auth_pwd->lpw.length = auth_key->local_password_length;
9413 	dfc_auth_pwd->lpw.type = auth_key->local_password_type;
9414 	/*
9415 	 * bcopy(auth_key->local_password, dfc_auth_pwd->lpw.password,
9416 	 * dfc_auth_pwd->lpw.length);
9417 	 */
9418 
9419 	dfc_auth_pwd->rpw.length = auth_key->remote_password_length;
9420 	dfc_auth_pwd->rpw.type = auth_key->remote_password_type;
9421 	/*
9422 	 * bcopy(auth_key->remote_password, dfc_auth_pwd->rpw.password,
9423 	 * dfc_auth_pwd->rpw.length);
9424 	 */
9425 
9426 	dfc_auth_pwd->lpw_new.length = auth_key->local_password_length;
9427 	dfc_auth_pwd->lpw_new.type = auth_key->local_password_type;
9428 	/*
9429 	 * bcopy(auth_key->local_password, dfc_auth_pwd->lpw_new.password,
9430 	 * dfc_auth_pwd->lpw_new.length);
9431 	 */
9432 
9433 	dfc_auth_pwd->rpw_new.length = auth_key->remote_password_length;
9434 	dfc_auth_pwd->rpw_new.type = auth_key->remote_password_type;
9435 	/*
9436 	 * bcopy(auth_key->remote_password, dfc_auth_pwd->rpw_new.password,
9437 	 * dfc_auth_pwd->rpw_new.length);
9438 	 */
9439 
9440 	mutex_exit(&hba->auth_lock);
9441 
9442 	return (0);
9443 
9444 } /* emlxs_dhc_get_auth_key() */
9445 
9446 
9447 /* Provides DFC support for emlxs_dfc_set_auth_key() */
9448 extern uint32_t
emlxs_dhc_set_auth_key(emlxs_hba_t * hba,dfc_auth_password_t * dfc_pwd)9449 emlxs_dhc_set_auth_key(emlxs_hba_t *hba, dfc_auth_password_t *dfc_pwd)
9450 {
9451 	emlxs_port_t *port = &PPORT;
9452 	emlxs_config_t *cfg = &CFG;
9453 	emlxs_auth_key_t *auth_key;
9454 	uint32_t length;
9455 
9456 	/* Return is authentication is not enabled */
9457 	if (cfg[CFG_AUTH_ENABLE].current == 0) {
9458 		EMLXS_MSGF(EMLXS_CONTEXT,
9459 		    &emlxs_fcsp_debug_msg,
9460 		    "dhc_set_auth_key. Auth disabled.");
9461 
9462 		return (DFC_AUTH_AUTHENTICATION_DISABLED);
9463 	}
9464 
9465 	/* Check to make sure localpwd does not equal to remotepwd */
9466 	/* if they are given in the same time, if not, see below  */
9467 	if ((dfc_pwd->lpw_new.type == PASSWORD_TYPE_ASCII ||
9468 	    dfc_pwd->lpw_new.type == PASSWORD_TYPE_BINARY) &&
9469 	    (dfc_pwd->rpw_new.type == PASSWORD_TYPE_ASCII ||
9470 	    dfc_pwd->rpw_new.type == PASSWORD_TYPE_BINARY)) {
9471 		if (bcmp(dfc_pwd->lpw_new.password,
9472 		    dfc_pwd->rpw_new.password,
9473 		    dfc_pwd->lpw_new.length) == 0) {
9474 			EMLXS_MSGF(EMLXS_CONTEXT,
9475 			    &emlxs_fcsp_debug_msg,
9476 			    "dhc_set_auth_key. nlpwd==nrpwd");
9477 
9478 			return (DFC_AUTH_LOCAL_REMOTE_PWD_EQUAL);
9479 		}
9480 	}
9481 
9482 	mutex_enter(&hba->auth_lock);
9483 
9484 	auth_key = emlxs_auth_key_get(hba,
9485 	    (uint8_t *)&dfc_pwd->lwwpn,
9486 	    (uint8_t *)&dfc_pwd->rwwpn);
9487 
9488 	/* If entry does not exist, then create entry */
9489 	if (!auth_key) {
9490 		auth_key = emlxs_auth_key_create(hba,
9491 		    (uint8_t *)&dfc_pwd->lwwpn,
9492 		    (uint8_t *)&dfc_pwd->rwwpn);
9493 
9494 		if (!auth_key) {
9495 			EMLXS_MSGF(EMLXS_CONTEXT,
9496 			    &emlxs_dfc_error_msg,
9497 			    "dhc_set_auth_key: Out of memory.");
9498 
9499 			mutex_exit(&hba->auth_lock);
9500 
9501 			return (DFC_SYSRES_ERROR);
9502 		}
9503 	}
9504 
9505 	/* Check if a new local password is provided */
9506 	if (dfc_pwd->lpw_new.type == PASSWORD_TYPE_ASCII ||
9507 	    dfc_pwd->lpw_new.type == PASSWORD_TYPE_BINARY) {
9508 		/* Check if current password should be checked */
9509 		if (auth_key->local_password_type == PASSWORD_TYPE_ASCII ||
9510 		    auth_key->local_password_type == PASSWORD_TYPE_BINARY) {
9511 			/* Verify current local password */
9512 			if ((auth_key->local_password_length !=
9513 			    dfc_pwd->lpw.length) ||
9514 			    (auth_key->local_password_type !=
9515 			    dfc_pwd->lpw.type) ||
9516 			    bcmp(dfc_pwd->lpw.password,
9517 			    auth_key->local_password,
9518 			    dfc_pwd->lpw.length)) {
9519 			EMLXS_MSGF(EMLXS_CONTEXT,
9520 			    &emlxs_dfc_error_msg,
9521 			    "dhc_set_auth_key: Invalid local password.");
9522 
9523 				mutex_exit(&hba->auth_lock);
9524 
9525 				return (DFC_AUTH_COMPARE_FAILED);
9526 			}
9527 		}
9528 
9529 		/*
9530 		 * Make sure the new local pwd is not equal to the current
9531 		 * remote pwd if any
9532 		 */
9533 		if (auth_key->remote_password_type == PASSWORD_TYPE_ASCII ||
9534 		    auth_key->remote_password_type == PASSWORD_TYPE_BINARY) {
9535 			if ((auth_key->remote_password_length ==
9536 			    dfc_pwd->lpw_new.length) &&
9537 			    (bcmp(dfc_pwd->lpw_new.password,
9538 			    auth_key->remote_password,
9539 			    dfc_pwd->lpw_new.length) == 0)) {
9540 			EMLXS_MSGF(EMLXS_CONTEXT,
9541 			    &emlxs_dfc_error_msg,
9542 			    "dhc_set_auth_key: nlpwd==crpwd");
9543 
9544 				mutex_exit(&hba->auth_lock);
9545 
9546 				return (DFC_AUTH_LOCAL_REMOTE_PWD_EQUAL);
9547 			}
9548 		}
9549 		/* Update local entry */
9550 		auth_key->local_password_length = dfc_pwd->lpw_new.length;
9551 		auth_key->local_password_type = dfc_pwd->lpw_new.type;
9552 		bzero(auth_key->local_password,
9553 		    sizeof (auth_key->local_password));
9554 		length = min(dfc_pwd->lpw_new.length,
9555 		    sizeof (auth_key->local_password));
9556 		bcopy(dfc_pwd->lpw_new.password,
9557 		    auth_key->local_password, length);
9558 	}
9559 	/* Check if a new remote password is provided */
9560 	if (dfc_pwd->rpw_new.type == PASSWORD_TYPE_ASCII ||
9561 	    dfc_pwd->rpw_new.type == PASSWORD_TYPE_BINARY) {
9562 		/* Check if current password should be checked */
9563 		if (auth_key->remote_password_type == PASSWORD_TYPE_ASCII ||
9564 		    auth_key->remote_password_type == PASSWORD_TYPE_BINARY) {
9565 			/* Verify current remote password */
9566 			if ((auth_key->remote_password_length !=
9567 			    dfc_pwd->rpw.length) ||
9568 			    (auth_key->remote_password_type !=
9569 			    dfc_pwd->rpw.type) ||
9570 			    bcmp(dfc_pwd->rpw.password,
9571 			    auth_key->remote_password,
9572 			    dfc_pwd->rpw.length)) {
9573 			EMLXS_MSGF(EMLXS_CONTEXT,
9574 			    &emlxs_dfc_error_msg,
9575 			    "dhc_set_auth_key: Invalid remote password.");
9576 
9577 				mutex_exit(&hba->auth_lock);
9578 
9579 				return (DFC_AUTH_COMPARE_FAILED);
9580 			}
9581 		}
9582 
9583 		/*
9584 		 * Make sure the new remote pwd is not equal to the current
9585 		 * local pwd if any
9586 		 */
9587 		if (auth_key->local_password_type == PASSWORD_TYPE_ASCII ||
9588 		    auth_key->local_password_type == PASSWORD_TYPE_BINARY) {
9589 			if ((auth_key->local_password_length ==
9590 			    dfc_pwd->rpw_new.length) &&
9591 			    (bcmp(dfc_pwd->rpw_new.password,
9592 			    auth_key->local_password,
9593 			    dfc_pwd->rpw_new.length) == 0)) {
9594 			EMLXS_MSGF(EMLXS_CONTEXT,
9595 			    &emlxs_dfc_error_msg,
9596 			    "dhc_set_auth_key: nrpwd==clpwd");
9597 
9598 				mutex_exit(&hba->auth_lock);
9599 
9600 				return (DFC_AUTH_LOCAL_REMOTE_PWD_EQUAL);
9601 			}
9602 		}
9603 		/* Update remote entry */
9604 		auth_key->remote_password_length = dfc_pwd->rpw_new.length;
9605 		auth_key->remote_password_type = dfc_pwd->rpw_new.type;
9606 		bzero(auth_key->remote_password,
9607 		    sizeof (auth_key->remote_password));
9608 		length = min(dfc_pwd->rpw_new.length, 128);
9609 		bcopy(dfc_pwd->rpw_new.password,
9610 		    auth_key->remote_password, length);
9611 	}
9612 	/* Update dfc local entry */
9613 	dfc_pwd->lpw.length = auth_key->local_password_length;
9614 	dfc_pwd->lpw.type = auth_key->local_password_type;
9615 	bzero(dfc_pwd->lpw.password, sizeof (dfc_pwd->lpw.password));
9616 	length = min(auth_key->local_password_length,
9617 	    sizeof (dfc_pwd->lpw.password));
9618 	bcopy(auth_key->local_password, dfc_pwd->lpw.password, length);
9619 
9620 	/* Update dfc remote entry */
9621 	dfc_pwd->rpw.length = auth_key->remote_password_length;
9622 	dfc_pwd->rpw.type = auth_key->remote_password_type;
9623 	bzero(dfc_pwd->rpw.password, sizeof (dfc_pwd->rpw.password));
9624 	length = min(auth_key->remote_password_length,
9625 	    sizeof (dfc_pwd->rpw.password));
9626 	bcopy(auth_key->remote_password, dfc_pwd->rpw.password, length);
9627 
9628 	emlxs_auth_key_print(hba, auth_key);
9629 
9630 	mutex_exit(&hba->auth_lock);
9631 
9632 	return (0);
9633 
9634 } /* emlxs_dhc_set_auth_key() */
9635 
9636 
9637 /* Provides DFC support for emlxs_dfc_get_auth_status() */
9638 extern uint32_t
emlxs_dhc_get_auth_status(emlxs_hba_t * hba,dfc_auth_status_t * fcsp_status)9639 emlxs_dhc_get_auth_status(emlxs_hba_t *hba, dfc_auth_status_t *fcsp_status)
9640 {
9641 	emlxs_port_t *port = &PPORT;
9642 	emlxs_config_t *cfg = &CFG;
9643 	char s_lwwpn[64];
9644 	char s_rwwpn[64];
9645 	emlxs_auth_cfg_t *auth_cfg;
9646 	dfc_auth_status_t *auth_status;
9647 	NODELIST *ndlp;
9648 	uint32_t rc;
9649 	time_t auth_time;
9650 	uint32_t update;
9651 
9652 	/* Return is authentication is not enabled */
9653 	if (cfg[CFG_AUTH_ENABLE].current == 0) {
9654 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_debug_msg,
9655 		    "dhc_get_auth_status. Auth disabled.");
9656 
9657 		return (DFC_AUTH_AUTHENTICATION_DISABLED);
9658 	}
9659 	mutex_enter(&hba->auth_lock);
9660 
9661 	auth_cfg = emlxs_auth_cfg_get(hba, (uint8_t *)&fcsp_status->lwwpn,
9662 	    (uint8_t *)&fcsp_status->rwwpn);
9663 
9664 	if (!auth_cfg) {
9665 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9666 		    "dhc_get_auth_status: entry not found. %s:%s",
9667 		    emlxs_wwn_xlate(s_lwwpn, sizeof (s_lwwpn),
9668 		    (uint8_t *)&fcsp_status->lwwpn),
9669 		    emlxs_wwn_xlate(s_rwwpn, sizeof (s_rwwpn),
9670 		    (uint8_t *)&fcsp_status->rwwpn));
9671 
9672 		mutex_exit(&hba->auth_lock);
9673 
9674 		return (DFC_AUTH_NOT_CONFIGURED);
9675 	}
9676 	if (bcmp((uint8_t *)&fcsp_status->rwwpn,
9677 	    (uint8_t *)emlxs_fabric_wwn, 8) == 0) {
9678 		auth_status = &port->port_dhc.auth_status;
9679 		auth_time = port->port_dhc.auth_time;
9680 		ndlp = emlxs_node_find_did(port, FABRIC_DID, 1);
9681 	} else {
9682 		auth_status = &auth_cfg->auth_status;
9683 		auth_time = auth_cfg->auth_time;
9684 		ndlp = auth_cfg->node;
9685 	}
9686 
9687 	update = 0;
9688 
9689 	/* Check if node is still available */
9690 	if (ndlp && ndlp->nlp_active) {
9691 		emlxs_dhc_status(port, ndlp, 0, 0);
9692 		update = 1;
9693 	} else {
9694 		rc = DFC_AUTH_WWN_NOT_FOUND;
9695 	}
9696 
9697 
9698 	if (update) {
9699 		fcsp_status->auth_state = auth_status->auth_state;
9700 		fcsp_status->auth_failReason = auth_status->auth_failReason;
9701 		fcsp_status->type_priority = auth_status->type_priority;
9702 		fcsp_status->group_priority = auth_status->group_priority;
9703 		fcsp_status->hash_priority = auth_status->hash_priority;
9704 		fcsp_status->localAuth = auth_status->localAuth;
9705 		fcsp_status->remoteAuth = auth_status->remoteAuth;
9706 		fcsp_status->time_from_last_auth = DRV_TIME - auth_time;
9707 		fcsp_status->time_until_next_auth =
9708 		    auth_status->time_until_next_auth;
9709 
9710 		rc = 0;
9711 	} else {
9712 		rc = DFC_AUTH_WWN_NOT_FOUND;
9713 	}
9714 
9715 	mutex_exit(&hba->auth_lock);
9716 
9717 	return (rc);
9718 
9719 } /* emlxs_dhc_get_auth_status() */
9720 
9721 
9722 /* Provides DFC support for emlxs_dfc_get_auth_list() */
9723 /* auth_lock must be held when calling. */
9724 /* fcsp_cfg must be large enough to hold hba->auth_cfg_count entries */
9725 extern uint32_t
emlxs_dhc_get_auth_cfg_table(emlxs_hba_t * hba,dfc_fcsp_config_t * fcsp_cfg)9726 emlxs_dhc_get_auth_cfg_table(emlxs_hba_t *hba, dfc_fcsp_config_t *fcsp_cfg)
9727 {
9728 	emlxs_port_t *port = &PPORT;
9729 	emlxs_config_t *cfg = &CFG;
9730 	emlxs_auth_cfg_t *auth_cfg;
9731 	uint32_t i;
9732 
9733 	/* Return if authentication is not enabled */
9734 	if (cfg[CFG_AUTH_ENABLE].current == 0) {
9735 		EMLXS_MSGF(EMLXS_CONTEXT,
9736 		    &emlxs_fcsp_debug_msg,
9737 		    "dhc_get_auth_cfg_table. Auth disabled.");
9738 
9739 		return (DFC_AUTH_AUTHENTICATION_DISABLED);
9740 	}
9741 	for (auth_cfg = hba->auth_cfg.next;
9742 	    auth_cfg != &hba->auth_cfg;
9743 	    auth_cfg = auth_cfg->next) {
9744 		bcopy((uint8_t *)&auth_cfg->local_entity,
9745 		    (uint8_t *)&fcsp_cfg->lwwpn, 8);
9746 		bcopy((uint8_t *)&auth_cfg->remote_entity,
9747 		    (uint8_t *)&fcsp_cfg->rwwpn, 8);
9748 
9749 		fcsp_cfg->auth_tov = auth_cfg->authentication_timeout;
9750 		fcsp_cfg->auth_mode = auth_cfg->authentication_mode;
9751 		fcsp_cfg->auth_bidir = auth_cfg->bidirectional;
9752 
9753 		for (i = 0; i < 4; i++) {
9754 			fcsp_cfg->type_priority[i] =
9755 			    auth_cfg->authentication_type_priority[i];
9756 			fcsp_cfg->hash_priority[i] =
9757 			    auth_cfg->hash_priority[i];
9758 		}
9759 
9760 		for (i = 0; i < 8; i++) {
9761 			fcsp_cfg->group_priority[i] =
9762 			    auth_cfg->dh_group_priority[i];
9763 		}
9764 
9765 		fcsp_cfg->reauth_tov = auth_cfg->reauthenticate_time_interval;
9766 
9767 		fcsp_cfg++;
9768 	}
9769 
9770 	return (0);
9771 
9772 } /* emlxs_dhc_get_auth_cfg_table() */
9773 
9774 
9775 
9776 /* Provides DFC support for emlxs_dfc_get_auth_list() */
9777 /* auth_lock must be held when calling. */
9778 /* auth_pwd must be large enough to hold hba->auth_key_count entries */
9779 extern uint32_t
emlxs_dhc_get_auth_key_table(emlxs_hba_t * hba,dfc_auth_password_t * auth_pwd)9780 emlxs_dhc_get_auth_key_table(emlxs_hba_t *hba, dfc_auth_password_t *auth_pwd)
9781 {
9782 	emlxs_port_t *port = &PPORT;
9783 	emlxs_config_t *cfg = &CFG;
9784 	emlxs_auth_key_t *auth_key;
9785 
9786 	/* Return if authentication is not enabled */
9787 	if (cfg[CFG_AUTH_ENABLE].current == 0) {
9788 		EMLXS_MSGF(EMLXS_CONTEXT,
9789 		    &emlxs_fcsp_debug_msg,
9790 		    "dhc_get_auth_key_table. Auth disabled.");
9791 
9792 		return (DFC_AUTH_AUTHENTICATION_DISABLED);
9793 	}
9794 	for (auth_key = hba->auth_key.next;
9795 	    auth_key != &hba->auth_key;
9796 	    auth_key = auth_key->next) {
9797 		bcopy((uint8_t *)&auth_key->local_entity,
9798 		    (uint8_t *)&auth_pwd->lwwpn, 8);
9799 		bcopy((uint8_t *)&auth_key->remote_entity,
9800 		    (uint8_t *)&auth_pwd->rwwpn, 8);
9801 
9802 		auth_pwd->lpw.length = auth_key->local_password_length;
9803 		auth_pwd->lpw.type = auth_key->local_password_type;
9804 		/*
9805 		 * bcopy(auth_key->local_password, auth_pwd->lpw.password,
9806 		 * auth_pwd->lpw.length);
9807 		 */
9808 
9809 		auth_pwd->rpw.length = auth_key->remote_password_length;
9810 		auth_pwd->rpw.type = auth_key->remote_password_type;
9811 		/*
9812 		 * bcopy(auth_key->remote_password, auth_pwd->rpw.password,
9813 		 * auth_pwd->rpw.length);
9814 		 */
9815 
9816 		auth_pwd->lpw_new.length = auth_key->local_password_length;
9817 		auth_pwd->lpw_new.type = auth_key->local_password_type;
9818 		/*
9819 		 * bcopy(auth_key->local_password,
9820 		 * auth_pwd->lpw_new.password, auth_pwd->lpw_new.length);
9821 		 */
9822 
9823 		auth_pwd->rpw_new.length = auth_key->remote_password_length;
9824 		auth_pwd->rpw_new.type = auth_key->remote_password_type;
9825 		/*
9826 		 * bcopy(auth_key->remote_password,
9827 		 * auth_pwd->rpw_new.password, auth_pwd->rpw_new.length);
9828 		 */
9829 
9830 		auth_pwd++;
9831 	}
9832 
9833 	return (0);
9834 
9835 } /* emlxs_dhc_get_auth_key_table() */
9836 
9837 #endif	/* DHCHAP_SUPPORT */
9838