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