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