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