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