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 *
emlxs_dhc_event_xlate(uint32_t state)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
emlxs_dhc_state(emlxs_port_t * port,emlxs_node_t * ndlp,uint32_t state,uint32_t reason,uint32_t explaination)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
emlxs_dhc_status(emlxs_port_t * port,emlxs_node_t * ndlp,uint32_t reason,uint32_t explaination)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 *
emlxs_dhc_pstate_xlate(uint32_t state)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 *
emlxs_dhc_nstate_xlate(uint32_t state)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
emlxs_check_dhgp(emlxs_port_t * port,NODELIST * ndlp,uint32_t * dh_id,uint16_t cnt,uint32_t * dhgp_id)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
emlxs_get_random_bytes(NODELIST * ndlp,uint8_t * rdn,uint32_t len)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
emlxs_dhchap_state_machine(emlxs_port_t * port,CHANNEL * cp,IOCBQ * iocbq,MATCHMAP * mp,NODELIST * ndlp,int evt)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
emlxs_disc_neverdev(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)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
emlxs_cmpl_dhchap_challenge_issue(fc_packet_t * pkt)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
emlxs_cmpl_dhchap_success_issue(fc_packet_t * pkt)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
emlxs_issue_dhchap_success(emlxs_port_t * port,NODELIST * ndlp,int retry,uint8_t * rsp)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
emlxs_cmpl_auth_reject_issue(fc_packet_t * pkt)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
emlxs_issue_auth_reject(emlxs_port_t * port,NODELIST * ndlp,int retry,uint32_t * arg,uint8_t ReasonCode,uint8_t ReasonCodeExplanation)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 *
emlxs_prep_els_fc_pkt(emlxs_port_t * port,uint32_t d_id,uint32_t cmd_size,uint32_t rsp_size,uint32_t datalen,int32_t sleepflag)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
emlxs_issue_auth_negotiate(emlxs_port_t * port,emlxs_node_t * ndlp,uint8_t retry)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
emlxs_cmpl_auth_negotiate_issue(fc_packet_t * pkt)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
emlxs_cmpl_auth_msg_auth_negotiate_issue(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)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
emlxs_rcv_auth_msg_auth_negotiate_issue(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)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
emlxs_cmpl_dhchap_reply_issue(fc_packet_t * pkt)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
emlxs_issue_dhchap_challenge(emlxs_port_t * port,NODELIST * ndlp,int retry,void * arg,uint32_t payload_len,uint32_t hash_id,uint32_t dhgp_id)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
emlxs_issue_dhchap_reply(emlxs_port_t * port,NODELIST * ndlp,int retry,uint32_t * arg1,uint8_t * dhval,uint32_t dhval_len,uint8_t * arg2,uint32_t arg2_len)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
emlxs_rcv_auth_msg_auth_negotiate_cmpl_wait4next(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)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
emlxs_cmpl_auth_msg_auth_negotiate_cmpl_wait4next(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)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
emlxs_rcv_auth_msg_dhchap_reply_issue(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)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
emlxs_cmpl_auth_msg_dhchap_reply_issue(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)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
emlxs_rcv_auth_msg_dhchap_reply_cmpl_wait4next(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)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
emlxs_cmpl_auth_msg_dhchap_reply_cmpl_wait4next(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)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
emlxs_rcv_auth_msg_dhchap_success_issue_wait4next(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)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
emlxs_cmpl_auth_msg_dhchap_success_issue_wait4next(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)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
emlxs_cmpl_auth_msg_auth_negotiate_rcv(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)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
emlxs_rcv_auth_msg_dhchap_challenge_issue(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)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
emlxs_cmpl_auth_msg_dhchap_challenge_issue(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)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
emlxs_rcv_auth_msg_dhchap_challenge_cmpl_wait4next(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)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
emlxs_cmpl_auth_msg_dhchap_challenge_cmpl_wait4next(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)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
emlxs_rcv_auth_msg_dhchap_success_issue(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)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
emlxs_cmpl_auth_msg_dhchap_success_issue(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)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
emlxs_device_recov_unmapped_node(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)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
emlxs_device_rm_npr_node(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)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
emlxs_device_recov_npr_node(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)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
emlxs_device_rem_auth(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)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
emlxs_device_recov_auth(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)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
emlxs_rcv_auth_msg_dhchap_success_cmpl_wait4next(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)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
emlxs_cmpl_auth_msg_dhchap_success_cmpl_wait4next(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)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
emlxs_rcv_auth_msg_auth_negotiate_rcv(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)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
emlxs_rcv_auth_msg_npr_node(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)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
emlxs_cmpl_auth_msg_npr_node(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)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
emlxs_rcv_auth_msg_unmapped_node(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)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 *
emlxs_hash_vrf(emlxs_port_t * port,emlxs_port_dhc_t * port_dhc,NODELIST * ndlp,uint32_t tran_id,union challenge_val un_cval)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 *
emlxs_hash_rsp(emlxs_port_t * port,emlxs_port_dhc_t * port_dhc,NODELIST * ndlp,uint32_t tran_id,union challenge_val un_cval,uint8_t * dhval,uint32_t dhvallen)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
emlxs_interm_hash(emlxs_port_t * port,emlxs_port_dhc_t * port_dhc,NODELIST * ndlp,void * hash_val,uint32_t tran_id,union challenge_val un_cval,uint8_t * dhval,uint32_t * dhvallen)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
emlxs_BIGNUM_get_pubkey(emlxs_port_t * port,emlxs_port_dhc_t * port_dhc,NODELIST * ndlp,uint8_t * dhval,uint32_t * dhvallen,uint32_t hash_size,uint32_t dhgp_id)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
emlxs_BIGNUM_get_dhval(emlxs_port_t * port,emlxs_port_dhc_t * port_dhc,NODELIST * ndlp,uint8_t * dhval,uint32_t * dhval_len,uint32_t dhgp_id,uint8_t * priv_key,uint32_t privkey_len)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
emlxs_BIGNUM_pubkey(emlxs_port_t * port,void * pubkey,uint8_t * dhval,uint32_t dhvallen,uint8_t * key,uint32_t key_size,uint32_t dhgp_id,uint32_t * pubkeylen)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
emlxs_hash_Cai(emlxs_port_t * port,emlxs_port_dhc_t * port_dhc,NODELIST * ndlp,void * Cai,uint32_t hash_id,uint32_t dhgp_id,uint32_t tran_id,uint8_t * cval,uint32_t cval_len,uint8_t * key,uint8_t * dhval,uint32_t dhvallen)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 *
emlxs_hash_verification(emlxs_port_t * port,emlxs_port_dhc_t * port_dhc,NODELIST * ndlp,uint32_t tran_id,uint8_t * dhval,uint32_t dhval_len,uint32_t flag,uint8_t * bi_cval)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 *
emlxs_hash_get_R2(emlxs_port_t * port,emlxs_port_dhc_t * port_dhc,NODELIST * ndlp,uint32_t tran_id,uint8_t * dhval,uint32_t dhval_len,uint32_t flag,uint8_t * bi_cval)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
emlxs_log_auth_event(emlxs_port_t * port,NODELIST * ndlp,char * subclass,char * info)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
emlxs_dhc_auth_start(emlxs_port_t * port,emlxs_node_t * ndlp,uint8_t * deferred_sbp,uint8_t * deferred_ubp)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
emlxs_dhc_auth_stop(emlxs_port_t * port,emlxs_node_t * ndlp)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
emlxs_dhc_auth_complete(emlxs_port_t * port,emlxs_node_t * ndlp,uint32_t status)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
emlxs_dhc_attach(emlxs_hba_t * hba)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
emlxs_dhc_detach(emlxs_hba_t * hba)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
emlxs_dhc_init_sp(emlxs_port_t * port,uint32_t did,SERV_PARM * sp,char ** msg)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
emlxs_dhc_verify_login(emlxs_port_t * port,uint32_t sid,SERV_PARM * sp)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
emlxs_dhc_reauth_timeout(emlxs_port_t * port,void * arg1,void * arg2)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
emlxs_dhc_set_reauth_time(emlxs_port_t * port,emlxs_node_t * ndlp,uint32_t status)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
emlxs_dhc_authrsp_timeout(emlxs_port_t * port,void * arg1,void * arg2)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 *
emlxs_auth_cfg_find(emlxs_port_t * port,uint8_t * rwwpn)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
emlxs_auth_cfg_init(emlxs_hba_t * hba)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
emlxs_auth_cfg_fini(emlxs_hba_t * hba)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
emlxs_auth_cfg_print(emlxs_hba_t * hba,emlxs_auth_cfg_t * auth_cfg)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 *
emlxs_auth_cfg_get(emlxs_hba_t * hba,uint8_t * lwwpn,uint8_t * rwwpn)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 *
emlxs_auth_cfg_create(emlxs_hba_t * hba,uint8_t * lwwpn,uint8_t * rwwpn)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
emlxs_auth_cfg_destroy(emlxs_hba_t * hba,emlxs_auth_cfg_t * auth_cfg)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
emlxs_auth_cfg_read(emlxs_hba_t * hba)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
emlxs_auth_cfg_parse(emlxs_hba_t * hba,emlxs_auth_cfg_t * auth_cfg,char * prop_str)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 *
emlxs_auth_key_find(emlxs_port_t * port,uint8_t * rwwpn)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
emlxs_auth_key_init(emlxs_hba_t * hba)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
emlxs_auth_key_fini(emlxs_hba_t * hba)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
emlxs_auth_key_print(emlxs_hba_t * hba,emlxs_auth_key_t * auth_key)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 *
emlxs_auth_key_get(emlxs_hba_t * hba,uint8_t * lwwpn,uint8_t * rwwpn)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 *
emlxs_auth_key_create(emlxs_hba_t * hba,uint8_t * lwwpn,uint8_t * rwwpn)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
emlxs_auth_key_destroy(emlxs_hba_t * hba,emlxs_auth_key_t * auth_key)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
emlxs_auth_key_read(emlxs_hba_t * hba)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
emlxs_auth_key_parse(emlxs_hba_t * hba,emlxs_auth_key_t * auth_key,char * prop_str)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
emlxs_dhc_init_auth(emlxs_hba_t * hba,uint8_t * lwwpn,uint8_t * rwwpn)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
emlxs_dhc_get_auth_cfg(emlxs_hba_t * hba,dfc_fcsp_config_t * fcsp_cfg)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
emlxs_dhc_add_auth_cfg(emlxs_hba_t * hba,dfc_fcsp_config_t * fcsp_cfg,dfc_password_t * dfc_pwd)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
emlxs_dhc_delete_auth_cfg(emlxs_hba_t * hba,dfc_fcsp_config_t * fcsp_cfg,dfc_password_t * dfc_pwd)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
emlxs_dhc_get_auth_key(emlxs_hba_t * hba,dfc_auth_password_t * dfc_auth_pwd)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
emlxs_dhc_set_auth_key(emlxs_hba_t * hba,dfc_auth_password_t * dfc_pwd)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
emlxs_dhc_get_auth_status(emlxs_hba_t * hba,dfc_auth_status_t * fcsp_status)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
emlxs_dhc_get_auth_cfg_table(emlxs_hba_t * hba,dfc_fcsp_config_t * fcsp_cfg)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
emlxs_dhc_get_auth_key_table(emlxs_hba_t * hba,dfc_auth_password_t * auth_pwd)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