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