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 return (node_dhc->state);
3927
3928 } /* emlxs_rcv_auth_msg_dhchap_challenge_cmpl_wait4next */
3929
3930
3931
3932 /*
3933 * This routine should be emlxs_disc_neverdev.
3934 *
3935 */
3936 /* ARGSUSED */
3937 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)3938 emlxs_cmpl_auth_msg_dhchap_challenge_cmpl_wait4next(
3939 emlxs_port_t *port,
3940 /* CHANNEL * rp, */ void *arg1,
3941 /* IOCBQ * iocbq, */ void *arg2,
3942 /* MATCHMAP * mp, */ void *arg3,
3943 /* NODELIST * ndlp */ void *arg4,
3944 uint32_t evt)
3945 {
3946 NODELIST *ndlp = (NODELIST *)arg4;
3947
3948 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
3949 "cmpl_a_m_dhch_chall_cmpl_wait4next.0x%x. Not implemented.",
3950 ndlp->nlp_DID);
3951
3952 return (0);
3953
3954 } /* emlxs_cmpl_auth_msg_dhchap_challenge_cmpl_wait4next */
3955
3956
3957 /*
3958 * ! emlxs_rcv_auth_msg_dhchap_success_issue
3959 *
3960 * \pre \post \param phba \param ndlp \param arg \param evt \return
3961 * uint32_t \b Description:
3962 *
3963 * The host is the auth responder and the auth transaction is still in
3964 * progress, any unsolicited els auth msg is unexpected and
3965 * should not happen. If DHCHAP_Reject received, ACC back and move to next
3966 * state NPR_NODE. anything else, RJT and move to
3967 * NPR_NODE.
3968 */
3969 /* ARGSUSED */
3970 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)3971 emlxs_rcv_auth_msg_dhchap_success_issue(
3972 emlxs_port_t *port,
3973 /* CHANNEL * rp, */ void *arg1,
3974 /* IOCBQ * iocbq, */ void *arg2,
3975 /* MATCHMAP * mp, */ void *arg3,
3976 /* NODELIST * ndlp */ void *arg4,
3977 uint32_t evt)
3978 {
3979 NODELIST *ndlp = (NODELIST *)arg4;
3980
3981 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
3982 "rcv_a_m_dhch_success_issue called. did=0x%x. Not implemented.",
3983 ndlp->nlp_DID);
3984
3985 return (0);
3986
3987 } /* emlxs_rcv_auth_msg_dhchap_success_issue */
3988
3989
3990
3991 /*
3992 * emlxs_cmpl_auth_msg_dhchap_success_issue
3993 *
3994 * This routine is invoked when
3995 * host as the auth responder received the solicited response (ACC or RJT)
3996 * from the initiator that received DHCHAP_ Success.
3997 *
3998 * For uni-dirctional authentication, we are done so the next state =
3999 * REG_LOGIN for bi-directional authentication, we will expect
4000 * DHCHAP_Success msg. so the next state = DHCHAP_SUCCESS_CMPL_WAIT4NEXT
4001 * and start the emlxs_dhc_authrsp_timeout timer
4002 */
4003 /* ARGSUSED */
4004 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)4005 emlxs_cmpl_auth_msg_dhchap_success_issue(
4006 emlxs_port_t *port,
4007 /* CHANNEL * rp, */ void *arg1,
4008 /* IOCBQ * iocbq, */ void *arg2,
4009 /* MATCHMAP * mp, */ void *arg3,
4010 /* NODELIST * ndlp */ void *arg4,
4011 uint32_t evt)
4012 {
4013 NODELIST *ndlp = (NODELIST *)arg4;
4014 emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
4015
4016 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4017 "cmpl_a_m_dhch_success_issue: did=0x%x auth_bidir=0x%x",
4018 ndlp->nlp_DID, node_dhc->nlp_auth_bidir);
4019
4020 if (node_dhc->nlp_auth_bidir == 1) {
4021 /* we would expect the bi-dir authentication result */
4022
4023 /*
4024 * the next state should be
4025 * emlxs_rcv_auth_msg_dhchap_success_cmpl_wait4next
4026 */
4027 emlxs_dhc_state(port, ndlp,
4028 NODE_STATE_DHCHAP_SUCCESS_CMPL_WAIT4NEXT, 0, 0);
4029
4030 /* start the emlxs_dhc_authrsp_timeout timer */
4031 node_dhc->nlp_authrsp_tmo = DRV_TIME +
4032 node_dhc->auth_cfg.authentication_timeout;
4033 } else {
4034 node_dhc->flag &= ~NLP_REMOTE_AUTH;
4035
4036 emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_SUCCESS, 0, 0);
4037 emlxs_log_auth_event(port, ndlp,
4038 "cmpl_auth_msg_dhchap_success_issue",
4039 "Node-initiated-unidir-reauth-success");
4040 emlxs_dhc_auth_complete(port, ndlp, 0);
4041 }
4042
4043 return (node_dhc->state);
4044
4045 } /* emlxs_cmpl_auth_msg_dhchap_success_issue */
4046
4047
4048 /* ARGSUSED */
4049 static uint32_t
emlxs_device_recov_unmapped_node(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)4050 emlxs_device_recov_unmapped_node(
4051 emlxs_port_t *port,
4052 void *arg1,
4053 void *arg2,
4054 void *arg3,
4055 void *arg4,
4056 uint32_t evt)
4057 {
4058 NODELIST *ndlp = (NODELIST *)arg4;
4059
4060 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4061 "device_recov_unmapped_node called. 0x%x. Not implemented.",
4062 ndlp->nlp_DID);
4063
4064 return (0);
4065
4066 } /* emlxs_device_recov_unmapped_node */
4067
4068
4069
4070 /* ARGSUSED */
4071 static uint32_t
emlxs_device_rm_npr_node(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)4072 emlxs_device_rm_npr_node(
4073 emlxs_port_t *port,
4074 void *arg1,
4075 void *arg2,
4076 void *arg3,
4077 void *arg4,
4078 uint32_t evt)
4079 {
4080 NODELIST *ndlp = (NODELIST *)arg4;
4081
4082 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4083 "device_rm_npr_node called. 0x%x. Not implemented.",
4084 ndlp->nlp_DID);
4085
4086 return (0);
4087
4088 } /* emlxs_device_rm_npr_node */
4089
4090
4091 /* ARGSUSED */
4092 static uint32_t
emlxs_device_recov_npr_node(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)4093 emlxs_device_recov_npr_node(
4094 emlxs_port_t *port,
4095 void *arg1,
4096 void *arg2,
4097 void *arg3,
4098 void *arg4,
4099 uint32_t evt)
4100 {
4101 NODELIST *ndlp = (NODELIST *)arg4;
4102
4103 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4104 "device_recov_npr_node called. 0x%x. Not implemented.",
4105 ndlp->nlp_DID);
4106
4107 return (0);
4108
4109 } /* emlxs_device_recov_npr_node */
4110
4111
4112 /* ARGSUSED */
4113 static uint32_t
emlxs_device_rem_auth(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)4114 emlxs_device_rem_auth(
4115 emlxs_port_t *port,
4116 /* CHANNEL * rp, */ void *arg1,
4117 /* IOCBQ * iocbq, */ void *arg2,
4118 /* MATCHMAP * mp, */ void *arg3,
4119 /* NODELIST * ndlp */ void *arg4,
4120 uint32_t evt)
4121 {
4122 NODELIST *ndlp = (NODELIST *)arg4;
4123 emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
4124
4125 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4126 "device_rem_auth: 0x%x.",
4127 ndlp->nlp_DID);
4128
4129 emlxs_dhc_state(port, ndlp, NODE_STATE_UNKNOWN, 0, 0);
4130
4131 return (node_dhc->state);
4132
4133 } /* emlxs_device_rem_auth */
4134
4135
4136 /*
4137 * This routine is invoked when linkdown event happens during authentication
4138 */
4139 /* ARGSUSED */
4140 static uint32_t
emlxs_device_recov_auth(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)4141 emlxs_device_recov_auth(
4142 emlxs_port_t *port,
4143 /* CHANNEL * rp, */ void *arg1,
4144 /* IOCBQ * iocbq, */ void *arg2,
4145 /* MATCHMAP * mp, */ void *arg3,
4146 /* NODELIST * ndlp */ void *arg4,
4147 uint32_t evt)
4148 {
4149 NODELIST *ndlp = (NODELIST *)arg4;
4150 emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
4151
4152 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4153 "device_recov_auth: 0x%x.",
4154 ndlp->nlp_DID);
4155
4156 node_dhc->nlp_authrsp_tmo = 0;
4157
4158 emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_FAILED, 0, 0);
4159
4160 return (node_dhc->state);
4161
4162 } /* emlxs_device_recov_auth */
4163
4164
4165
4166 /*
4167 * This routine is invoked when the host as the responder sent out the
4168 * ELS DHCHAP_Success to the initiator, the initiator ACC
4169 * it. AND then the host received an unsolicited auth msg from the initiator,
4170 * this msg is supposed to be the ELS DHCHAP_Success
4171 * msg for the bi-directional authentication.
4172 *
4173 * next state should be REG_LOGIN
4174 */
4175 /* ARGSUSED */
4176 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)4177 emlxs_rcv_auth_msg_dhchap_success_cmpl_wait4next(
4178 emlxs_port_t *port,
4179 /* CHANNEL * rp, */ void *arg1,
4180 /* IOCBQ * iocbq, */ void *arg2,
4181 /* MATCHMAP * mp, */ void *arg3,
4182 /* NODELIST * ndlp */ void *arg4,
4183 uint32_t evt)
4184 {
4185 IOCBQ *iocbq = (IOCBQ *)arg2;
4186 MATCHMAP *mp = (MATCHMAP *)arg3;
4187 NODELIST *ndlp = (NODELIST *)arg4;
4188 emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
4189 uint8_t *bp;
4190 uint32_t *lp;
4191 DHCHAP_SUCCESS_HDR *dh_success;
4192 AUTH_RJT *auth_rjt;
4193 uint8_t ReasonCode;
4194 uint8_t ReasonCodeExplanation;
4195
4196 bp = mp->virt;
4197 lp = (uint32_t *)bp;
4198
4199 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4200 "rcv_auth_msg_dhchap_success_cmpl_wait4next: did=0x%x",
4201 ndlp->nlp_DID);
4202
4203 dh_success = (DHCHAP_SUCCESS_HDR *)((uint8_t *)lp);
4204
4205 (void) emlxs_els_reply(port, iocbq, ELS_CMD_ACC, ELS_CMD_AUTH, 0, 0);
4206
4207 if (dh_success->auth_msg_code == AUTH_REJECT) {
4208 /* ACC it and retry etc. */
4209 auth_rjt = (AUTH_RJT *)dh_success;
4210 ReasonCode = auth_rjt->ReasonCode;
4211 ReasonCodeExplanation = auth_rjt->ReasonCodeExplanation;
4212
4213 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4214 "rcv_a_m_dhch_success_cmpl_wait4next:REJECT rvd. 0x%x 0x%x 0x%x",
4215 ndlp->nlp_DID, ReasonCode, ReasonCodeExplanation);
4216
4217 switch (ReasonCode) {
4218 case AUTHRJT_LOGIC_ERR:
4219 switch (ReasonCodeExplanation) {
4220 case AUTHEXP_MECH_UNUSABLE:
4221 case AUTHEXP_DHGROUP_UNUSABLE:
4222 case AUTHEXP_HASHFUNC_UNUSABLE:
4223 ReasonCode = AUTHRJT_LOGIC_ERR;
4224 ReasonCodeExplanation = AUTHEXP_RESTART_AUTH;
4225 break;
4226
4227 case AUTHEXP_RESTART_AUTH:
4228 /*
4229 * Cancel the rsp timer if not cancelled yet.
4230 * and restart auth tran now.
4231 */
4232 if (node_dhc->nlp_authrsp_tmo != 0) {
4233 node_dhc->nlp_authrsp_tmo = 0;
4234 node_dhc->nlp_authrsp_tmocnt = 0;
4235 }
4236 if (emlxs_dhc_auth_start(port, ndlp,
4237 NULL, NULL) != 0) {
4238 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_debug_msg,
4239 "Reauth timeout. Auth initfailed. 0x%x %x",
4240 ndlp->nlp_DID, node_dhc->state);
4241 }
4242 return (node_dhc->state);
4243
4244 default:
4245 ReasonCode = AUTHRJT_FAILURE;
4246 ReasonCodeExplanation = AUTHEXP_AUTH_FAILED;
4247 break;
4248
4249 }
4250 break;
4251
4252 case AUTHRJT_FAILURE:
4253 default:
4254 ReasonCode = AUTHRJT_FAILURE;
4255 ReasonCodeExplanation = AUTHEXP_AUTH_FAILED;
4256 break;
4257
4258 }
4259
4260 goto Reject;
4261
4262 } else if (dh_success->auth_msg_code == DHCHAP_SUCCESS) {
4263 if (LE_SWAP32(dh_success->tran_id) !=
4264 node_dhc->nlp_auth_tranid_ini) {
4265 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4266 "rcv_a_m_dhch_success_cmpl_wait4next: 0x%x 0x%lx, 0x%lx",
4267 ndlp->nlp_DID, dh_success->tran_id, node_dhc->nlp_auth_tranid_ini);
4268
4269 ReasonCode = AUTHRJT_FAILURE;
4270 ReasonCodeExplanation = AUTHEXP_BAD_PROTOCOL;
4271 goto Reject;
4272 }
4273 node_dhc->flag |= NLP_REMOTE_AUTH;
4274
4275 emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_SUCCESS, 0, 0);
4276 emlxs_log_auth_event(port, ndlp,
4277 "rcv_auth_msg_dhchap_success_cmpl_wait4next",
4278 "Node-initiated-bidir-reauth-success");
4279 emlxs_dhc_auth_complete(port, ndlp, 0);
4280 } else {
4281 ReasonCode = AUTHRJT_FAILURE;
4282 ReasonCodeExplanation = AUTHEXP_BAD_PROTOCOL;
4283 goto Reject;
4284 }
4285
4286 return (node_dhc->state);
4287
4288 Reject:
4289
4290 emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_FAILED,
4291 ReasonCode, ReasonCodeExplanation);
4292 (void) emlxs_issue_auth_reject(port, ndlp, 0, 0, ReasonCode,
4293 ReasonCodeExplanation);
4294 emlxs_dhc_auth_complete(port, ndlp, 1);
4295
4296 return (node_dhc->state);
4297
4298 } /* emlxs_rcv_auth_msg_dhchap_success_cmpl_wait4next */
4299
4300
4301 /* ARGSUSED */
4302 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)4303 emlxs_cmpl_auth_msg_dhchap_success_cmpl_wait4next(
4304 emlxs_port_t *port,
4305 /* CHANNEL * rp, */ void *arg1,
4306 /* IOCBQ * iocbq, */ void *arg2,
4307 /* MATCHMAP * mp, */ void *arg3,
4308 /* NODELIST * ndlp */ void *arg4,
4309 uint32_t evt)
4310 {
4311
4312 return (0);
4313
4314 } /* emlxs_cmpl_auth_msg_dhchap_success_cmpl_wait4next */
4315
4316
4317 /* ARGSUSED */
4318 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)4319 emlxs_rcv_auth_msg_auth_negotiate_rcv(
4320 emlxs_port_t *port,
4321 /* CHANNEL * rp, */ void *arg1,
4322 /* IOCBQ * iocbq, */ void *arg2,
4323 /* MATCHMAP * mp, */ void *arg3,
4324 /* NODELIST * ndlp */ void *arg4,
4325 uint32_t evt)
4326 {
4327 NODELIST *ndlp = (NODELIST *)arg4;
4328
4329 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4330 "rcv_a_m_auth_negotiate_rcv called. did=0x%x. Not implemented.",
4331 ndlp->nlp_DID);
4332
4333 return (0);
4334
4335 } /* emlxs_rcv_auth_msg_auth_negotiate_rcv */
4336
4337
4338 /* ARGSUSED */
4339 static uint32_t
emlxs_rcv_auth_msg_npr_node(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)4340 emlxs_rcv_auth_msg_npr_node(
4341 emlxs_port_t *port,
4342 /* CHANNEL * rp, */ void *arg1,
4343 /* IOCBQ * iocbq, */ void *arg2,
4344 /* MATCHMAP * mp, */ void *arg3,
4345 /* NODELIST * ndlp */ void *arg4,
4346 uint32_t evt)
4347 {
4348 IOCBQ *iocbq = (IOCBQ *)arg2;
4349 MATCHMAP *mp = (MATCHMAP *)arg3;
4350 NODELIST *ndlp = (NODELIST *)arg4;
4351 emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
4352 uint8_t *bp;
4353
4354 uint32_t *lp;
4355 uint32_t msglen;
4356 uint8_t *tmp;
4357
4358 AUTH_MSG_HDR *msg;
4359
4360 uint8_t *temp;
4361 uint32_t rc, i, hs_id[2], dh_id[5];
4362 /* from initiator */
4363 uint32_t hash_id, dhgp_id; /* to be used by responder */
4364 uint16_t num_hs = 0;
4365 uint16_t num_dh = 0;
4366
4367 bp = mp->virt;
4368 lp = (uint32_t *)bp;
4369
4370 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4371 "rcv_auth_msg_npr_node:");
4372
4373 /*
4374 * 1. process the auth msg, should acc first no matter what. 2.
4375 * return DHCHAP_Challenge for AUTH_Negotiate auth msg, AUTH_Reject
4376 * for anything else.
4377 */
4378 (void) emlxs_els_reply(port, iocbq, ELS_CMD_ACC, ELS_CMD_AUTH, 0, 0);
4379
4380 msg = (AUTH_MSG_HDR *)((uint8_t *)lp);
4381 msglen = msg->msg_len;
4382 tmp = ((uint8_t *)lp);
4383
4384 /* temp is used for error checking */
4385 temp = (uint8_t *)((uint8_t *)lp);
4386 /* Check the auth_els_code */
4387 if (((*(uint32_t *)temp) & 0xFFFFFFFF) != LE_SWAP32(0x90000B01)) {
4388 /* ReasonCode = AUTHRJT_FAILURE; */
4389 /* ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD; */
4390
4391 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4392 "rcv_auth_msg_npr_node: payload(1)=0x%x",
4393 (*(uint32_t *)temp));
4394
4395 goto AUTH_Reject;
4396 }
4397 temp += 3 * sizeof (uint32_t);
4398 /* Check name tag and name length */
4399 if (((*(uint32_t *)temp) & 0xFFFFFFFF) != LE_SWAP32(0x00010008)) {
4400 /* ReasonCode = AUTHRJT_FAILURE; */
4401 /* ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD; */
4402
4403 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4404 "rcv_auth_msg_npr_node: payload(2)=0x%x",
4405 (*(uint32_t *)temp));
4406
4407 goto AUTH_Reject;
4408 }
4409 temp += sizeof (uint32_t) + 8;
4410 /* Check proto_num */
4411 if (((*(uint32_t *)temp) & 0xFFFFFFFF) != LE_SWAP32(0x00000001)) {
4412 /* ReasonCode = AUTHRJT_FAILURE; */
4413 /* ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD; */
4414
4415 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4416 "rcv_auth_msg_npr_node: payload(3)=0x%x",
4417 (*(uint32_t *)temp));
4418
4419 goto AUTH_Reject;
4420 }
4421 temp += sizeof (uint32_t);
4422 /* Get para_len */
4423 /* para_len = LE_SWAP32(*(uint32_t *)temp); */
4424
4425 temp += sizeof (uint32_t);
4426 /* Check proto_id */
4427 if (((*(uint32_t *)temp) & 0xFFFFFFFF) != AUTH_DHCHAP) {
4428 /* ReasonCode = AUTHRJT_FAILURE; */
4429 /* ReasonCodeExplanation = AUTHEXP_BAD_PROTOCOL; */
4430
4431 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4432 "rcv_auth_msg_npr_node: payload(4)=0x%x",
4433 (*(uint32_t *)temp));
4434
4435 goto AUTH_Reject;
4436 }
4437 temp += sizeof (uint32_t);
4438 /* Check hashlist tag */
4439 if ((LE_SWAP32(*(uint32_t *)temp) & 0xFFFF0000) >> 16 !=
4440 LE_SWAP16(HASH_LIST_TAG)) {
4441 /* ReasonCode = AUTHRJT_FAILURE; */
4442 /* ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD; */
4443
4444 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4445 "rcv_auth_msg_npr_node: payload(5)=0x%x",
4446 (LE_SWAP32(*(uint32_t *)temp) & 0xFFFF0000) >> 16);
4447
4448 goto AUTH_Reject;
4449 }
4450 /* Get num_hs */
4451 num_hs = LE_SWAP32(*(uint32_t *)temp) & 0x0000FFFF;
4452
4453 temp += sizeof (uint32_t);
4454 /* Check HashList_value1 */
4455 hs_id[0] = *(uint32_t *)temp;
4456
4457 if ((hs_id[0] != AUTH_MD5) && (hs_id[0] != AUTH_SHA1)) {
4458 /* ReasonCode = AUTHRJT_LOGIC_ERR; */
4459 /* ReasonCodeExplanation = AUTHEXP_HASHFUNC_UNUSABLE; */
4460
4461 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4462 "rcv_auth_msg_npr_node: payload(6)=0x%x",
4463 (*(uint32_t *)temp));
4464
4465 goto AUTH_Reject;
4466 }
4467 if (num_hs == 1) {
4468 hs_id[1] = 0;
4469 } else if (num_hs == 2) {
4470 temp += sizeof (uint32_t);
4471 hs_id[1] = *(uint32_t *)temp;
4472
4473 if ((hs_id[1] != AUTH_MD5) && (hs_id[1] != AUTH_SHA1)) {
4474 /* ReasonCode = AUTHRJT_LOGIC_ERR; */
4475 /* ReasonCodeExplanation = AUTHEXP_HASHFUNC_UNUSABLE; */
4476
4477 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4478 "rcv_auth_msg_npr_node: payload(7)=0x%x",
4479 (*(uint32_t *)temp));
4480
4481 goto AUTH_Reject;
4482 }
4483 if (hs_id[0] == hs_id[1]) {
4484 /* ReasonCode = AUTHRJT_FAILURE; */
4485 /* ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD; */
4486
4487 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4488 "rcv_auth_msg_npr_node: payload(8)=0x%x",
4489 (*(uint32_t *)temp));
4490
4491 goto AUTH_Reject;
4492 }
4493 } else {
4494 /* ReasonCode = AUTHRJT_FAILURE; */
4495 /* ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD; */
4496
4497 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4498 "rcv_auth_msg_npr_node: payload(9)=0x%x",
4499 (*(uint32_t *)(temp - sizeof (uint32_t))));
4500
4501 goto AUTH_Reject;
4502 }
4503
4504 /* Which hash_id should we use */
4505 if (num_hs == 1) {
4506 /*
4507 * We always use the highest priority specified by us if we
4508 * match initiator's , Otherwise, we use the next higher we
4509 * both have. CR 26238
4510 */
4511 if (node_dhc->auth_cfg.hash_priority[0] == hs_id[0]) {
4512 hash_id = node_dhc->auth_cfg.hash_priority[0];
4513 } else if (node_dhc->auth_cfg.hash_priority[1] == hs_id[0]) {
4514 hash_id = node_dhc->auth_cfg.hash_priority[1];
4515 } else {
4516 /* ReasonCode = AUTHRJT_LOGIC_ERR; */
4517 /* ReasonCodeExplanation = AUTHEXP_HASHFUNC_UNUSABLE; */
4518
4519 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4520 "rcv_auth_msg_npr_node: payload(10)=0x%lx",
4521 (*(uint32_t *)temp));
4522
4523 goto AUTH_Reject;
4524 }
4525 } else {
4526 /*
4527 * Since the initiator specified two hashs, we always select
4528 * our first one.
4529 */
4530 hash_id = node_dhc->auth_cfg.hash_priority[0];
4531 }
4532
4533 temp += sizeof (uint32_t);
4534 /* Check DHgIDList_tag */
4535 if ((LE_SWAP32(*(uint32_t *)temp) & 0xFFFF0000) >> 16 !=
4536 LE_SWAP16(DHGID_LIST_TAG)) {
4537 /* ReasonCode = AUTHRJT_FAILURE; */
4538 /* ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD; */
4539
4540 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4541 "rcv_auth_msg_npr_node: payload(11)=0x%lx",
4542 (*(uint32_t *)temp));
4543
4544 goto AUTH_Reject;
4545 }
4546 /* Get num_dh */
4547 num_dh = LE_SWAP32(*(uint32_t *)temp) & 0x0000FFFF;
4548
4549 if (num_dh == 0) {
4550 /* ReasonCode = AUTHRJT_FAILURE; */
4551 /* ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD; */
4552
4553 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4554 "rcv_auth_msg_npr_node: payload(12)=0x%lx",
4555 (*(uint32_t *)temp));
4556
4557 goto AUTH_Reject;
4558 }
4559 for (i = 0; i < num_dh; i++) {
4560 temp += sizeof (uint32_t);
4561 /* Check DHgIDList_g0 */
4562 dh_id[i] = (*(uint32_t *)temp);
4563 }
4564
4565 rc = emlxs_check_dhgp(port, ndlp, dh_id, num_dh, &dhgp_id);
4566
4567 if (rc == 1) {
4568 /* ReasonCode = AUTHRJT_LOGIC_ERR; */
4569 /* ReasonCodeExplanation = AUTHEXP_DHGROUP_UNUSABLE; */
4570
4571 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4572 "rcv_auth_msg_npr_node: payload(13)=0x%lx",
4573 (*(uint32_t *)temp));
4574
4575 goto AUTH_Reject;
4576 } else if (rc == 2) {
4577 /* ReasonCode = AUTHRJT_FAILURE; */
4578 /* ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD; */
4579
4580 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
4581 "rcv_auth_msg_npr_node: payload(14)=0x%lx",
4582 (*(uint32_t *)temp));
4583
4584 goto AUTH_Reject;
4585 }
4586 /* We should update the tran_id */
4587 node_dhc->nlp_auth_tranid_ini = msg->tran_id;
4588
4589 if (msg->auth_msg_code == AUTH_NEGOTIATE) {
4590 node_dhc->nlp_auth_flag = 1; /* ndlp is the initiator */
4591
4592 /* Send back the DHCHAP_Challenge with the proper paramaters */
4593 if (emlxs_issue_dhchap_challenge(port, ndlp, 0, tmp,
4594 LE_SWAP32(msglen),
4595 hash_id, dhgp_id)) {
4596 goto AUTH_Reject;
4597 }
4598 emlxs_dhc_state(port, ndlp,
4599 NODE_STATE_DHCHAP_CHALLENGE_ISSUE, 0, 0);
4600
4601 } else {
4602 goto AUTH_Reject;
4603 }
4604
4605 return (node_dhc->state);
4606
4607 AUTH_Reject:
4608
4609 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4610 "rcv_auth_msg_npr_node: AUTH_Reject it.");
4611
4612 return (node_dhc->state);
4613
4614 } /* emlxs_rcv_auth_msg_npr_node */
4615
4616
4617 /* ARGSUSED */
4618 static uint32_t
emlxs_cmpl_auth_msg_npr_node(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)4619 emlxs_cmpl_auth_msg_npr_node(
4620 emlxs_port_t *port,
4621 /* CHANNEL * rp, */ void *arg1,
4622 /* IOCBQ * iocbq, */ void *arg2,
4623 /* MATCHMAP * mp, */ void *arg3,
4624 /* NODELIST * ndlp */ void *arg4,
4625 uint32_t evt)
4626 {
4627 NODELIST *ndlp = (NODELIST *)arg4;
4628 emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
4629
4630 /*
4631 * we donot cancel the nodev timeout here because we donot know if we
4632 * can get the authentication restarted from other side once we got
4633 * the new auth transaction kicked off we cancel nodev tmo
4634 * immediately.
4635 */
4636 /* we goto change the hba state back to where it used to be */
4637 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4638 "cmpl_auth_msg_npr_node: 0x%x 0x%x prev_state=0x%x\n",
4639 ndlp->nlp_DID, node_dhc->state, node_dhc->prev_state);
4640
4641 return (node_dhc->state);
4642
4643 } /* emlxs_cmpl_auth_msg_npr_node */
4644
4645
4646 /*
4647 * ! emlxs_rcv_auth_msg_unmapped_node
4648 *
4649 * \pre \post \param phba \param ndlp \param arg \param evt \return
4650 * uint32_t
4651 *
4652 * \b Description: This routine is invoked when the host received an
4653 * unsolicited els authentication msg from the Fx_Port which is
4654 * wellknown port 0xFFFFFE in unmapped state, or from Nx_Port which is
4655 * in the unmapped state meaning that it is either a target
4656 * which there is no scsi id associated with it or it could be another
4657 * initiator. (end-to-end)
4658 *
4659 * For the Fabric F_Port (FFFFFE) we mark the port to the state in re_auth
4660 * state without disruppting the traffic. Then the fabric
4661 * will go through the authentication processes until it is done.
4662 *
4663 * most of the cases, the fabric should send us AUTH_Negotiate ELS msg. Once
4664 * host received this auth_negotiate els msg, host
4665 * should sent back ACC first and then send random challenge, plus DH value
4666 * (i.e., host's publick key)
4667 *
4668 * Host side needs to store the challenge value and public key for later
4669 * verification usage. (i.e., to verify the response from
4670 * initiator)
4671 *
4672 * If two FC_Ports start the reauthentication transaction at the same time,
4673 * one of the two authentication transactions shall be
4674 * aborted. In case of Host and Fabric the Nx_Port shall remain the
4675 * authentication initiator, while the Fx_Port shall become
4676 * the authentication responder.
4677 *
4678 */
4679 /* ARGSUSED */
4680 static uint32_t
emlxs_rcv_auth_msg_unmapped_node(emlxs_port_t * port,void * arg1,void * arg2,void * arg3,void * arg4,uint32_t evt)4681 emlxs_rcv_auth_msg_unmapped_node(
4682 emlxs_port_t *port,
4683 /* CHANNEL * rp, */ void *arg1,
4684 /* IOCBQ * iocbq, */ void *arg2,
4685 /* MATCHMAP * mp, */ void *arg3,
4686 /* NODELIST * ndlp */ void *arg4,
4687 uint32_t evt)
4688 {
4689 IOCBQ *iocbq = (IOCBQ *)arg2;
4690 MATCHMAP *mp = (MATCHMAP *)arg3;
4691 NODELIST *ndlp = (NODELIST *)arg4;
4692 emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
4693 uint8_t *bp;
4694 uint32_t *lp;
4695 uint32_t msglen;
4696 uint8_t *tmp;
4697
4698 uint8_t ReasonCode;
4699 uint8_t ReasonCodeExplanation;
4700 AUTH_MSG_HDR *msg;
4701 uint8_t *temp;
4702 uint32_t rc, i, hs_id[2], dh_id[5];
4703 /* from initiator */
4704 uint32_t hash_id, dhgp_id; /* to be used by responder */
4705 uint16_t num_hs = 0;
4706 uint16_t num_dh = 0;
4707
4708 /*
4709 * 1. process the auth msg, should acc first no matter what. 2.
4710 * return DHCHAP_Challenge for AUTH_Negotiate auth msg, AUTH_Reject
4711 * for anything else.
4712 */
4713 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4714 "rcv_auth_msg_unmapped_node: Sending ACC: did=0x%x",
4715 ndlp->nlp_DID);
4716
4717 (void) emlxs_els_reply(port, iocbq, ELS_CMD_ACC, ELS_CMD_AUTH, 0, 0);
4718
4719 bp = mp->virt;
4720 lp = (uint32_t *)bp;
4721
4722 msg = (AUTH_MSG_HDR *)((uint8_t *)lp);
4723 msglen = msg->msg_len;
4724
4725 tmp = ((uint8_t *)lp);
4726
4727 /* temp is used for error checking */
4728 temp = (uint8_t *)((uint8_t *)lp);
4729 /* Check the auth_els_code */
4730 if (((*(uint32_t *)temp) & 0xFFFFFFFF) != LE_SWAP32(0x90000B01)) {
4731 ReasonCode = AUTHRJT_FAILURE;
4732 ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD;
4733
4734 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4735 "rcv_auth_msg_unmapped_node: payload(1)=0x%x",
4736 (*(uint32_t *)temp));
4737
4738 goto AUTH_Reject;
4739 }
4740 temp += 3 * sizeof (uint32_t);
4741 /* Check name tag and name length */
4742 if (((*(uint32_t *)temp) & 0xFFFFFFFF) != LE_SWAP32(0x00010008)) {
4743 ReasonCode = AUTHRJT_FAILURE;
4744 ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD;
4745
4746 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4747 "rcv_auth_msg_unmapped_node: payload(2)=0x%x",
4748 (*(uint32_t *)temp));
4749
4750 goto AUTH_Reject;
4751 }
4752 temp += sizeof (uint32_t) + 8;
4753 /* Check proto_num */
4754 if (((*(uint32_t *)temp) & 0xFFFFFFFF) != LE_SWAP32(0x00000001)) {
4755 ReasonCode = AUTHRJT_FAILURE;
4756 ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD;
4757
4758 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4759 "rcv_auth_msg_unmapped_node: payload(3)=0x%x",
4760 (*(uint32_t *)temp));
4761
4762 goto AUTH_Reject;
4763 }
4764 temp += sizeof (uint32_t);
4765
4766 /* Get para_len */
4767 /* para_len = *(uint32_t *)temp; */
4768 temp += sizeof (uint32_t);
4769
4770 /* Check proto_id */
4771 if (((*(uint32_t *)temp) & 0xFFFFFFFF) != AUTH_DHCHAP) {
4772 ReasonCode = AUTHRJT_FAILURE;
4773 ReasonCodeExplanation = AUTHEXP_BAD_PROTOCOL;
4774
4775 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4776 "rcv_auth_msg_unmapped_node: payload(4)=0x%x",
4777 (*(uint32_t *)temp));
4778
4779 goto AUTH_Reject;
4780 }
4781 temp += sizeof (uint32_t);
4782 /* Check hashlist tag */
4783 if ((LE_SWAP32(*(uint32_t *)temp) & 0xFFFF0000) >> 16 !=
4784 LE_SWAP16(HASH_LIST_TAG)) {
4785 ReasonCode = AUTHRJT_FAILURE;
4786 ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD;
4787
4788 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4789 "rcv_auth_msg_unmapped_node: payload(5)=0x%x",
4790 (LE_SWAP32(*(uint32_t *)temp) & 0xFFFF0000) >> 16);
4791
4792 goto AUTH_Reject;
4793 }
4794 /* Get num_hs */
4795 num_hs = LE_SWAP32(*(uint32_t *)temp) & 0x0000FFFF;
4796
4797 temp += sizeof (uint32_t);
4798 /* Check HashList_value1 */
4799 hs_id[0] = *(uint32_t *)temp;
4800
4801 if ((hs_id[0] != AUTH_MD5) && (hs_id[0] != AUTH_SHA1)) {
4802 ReasonCode = AUTHRJT_LOGIC_ERR;
4803 ReasonCodeExplanation = AUTHEXP_HASHFUNC_UNUSABLE;
4804
4805 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4806 "rcv_auth_msg_unmapped_node: payload(6)=0x%x",
4807 (*(uint32_t *)temp));
4808
4809 goto AUTH_Reject;
4810 }
4811 if (num_hs == 1) {
4812 hs_id[1] = 0;
4813 } else if (num_hs == 2) {
4814 temp += sizeof (uint32_t);
4815 hs_id[1] = *(uint32_t *)temp;
4816
4817 if ((hs_id[1] != AUTH_MD5) && (hs_id[1] != AUTH_SHA1)) {
4818 ReasonCode = AUTHRJT_LOGIC_ERR;
4819 ReasonCodeExplanation = AUTHEXP_HASHFUNC_UNUSABLE;
4820
4821 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4822 "rcv_auth_msg_unmapped_node: payload(7)=0x%x",
4823 (*(uint32_t *)temp));
4824
4825 goto AUTH_Reject;
4826 }
4827 if (hs_id[0] == hs_id[1]) {
4828 ReasonCode = AUTHRJT_FAILURE;
4829 ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD;
4830
4831 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4832 "rcv_auth_msg_unmapped_node: payload(8)=0x%x",
4833 (*(uint32_t *)temp));
4834
4835 goto AUTH_Reject;
4836 }
4837 } else {
4838 ReasonCode = AUTHRJT_FAILURE;
4839 ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD;
4840
4841 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4842 "rcv_auth_msg_unmapped_node: payload(9)=0x%x",
4843 (*(uint32_t *)(temp - sizeof (uint32_t))));
4844
4845 goto AUTH_Reject;
4846 }
4847
4848 /* Which hash_id should we use */
4849 if (num_hs == 1) {
4850 /*
4851 * We always use the highest priority specified by us if we
4852 * match initiator's , Otherwise, we use the next higher we
4853 * both have. CR 26238
4854 */
4855 if (node_dhc->auth_cfg.hash_priority[0] == hs_id[0]) {
4856 hash_id = node_dhc->auth_cfg.hash_priority[0];
4857 } else if (node_dhc->auth_cfg.hash_priority[1] == hs_id[0]) {
4858 hash_id = node_dhc->auth_cfg.hash_priority[1];
4859 } else {
4860 ReasonCode = AUTHRJT_LOGIC_ERR;
4861 ReasonCodeExplanation = AUTHEXP_HASHFUNC_UNUSABLE;
4862
4863 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4864 "rcv_auth_msg_unmapped_node: pload(10)=0x%x",
4865 (*(uint32_t *)temp));
4866
4867 goto AUTH_Reject;
4868 }
4869 } else {
4870 /*
4871 * Since the initiator specified two hashs, we always select
4872 * our first one.
4873 */
4874 hash_id = node_dhc->auth_cfg.hash_priority[0];
4875 }
4876
4877 temp += sizeof (uint32_t);
4878 /* Check DHgIDList_tag */
4879 if ((LE_SWAP32(*(uint32_t *)temp) & 0xFFFF0000) >> 16 !=
4880 LE_SWAP16(DHGID_LIST_TAG)) {
4881 ReasonCode = AUTHRJT_FAILURE;
4882 ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD;
4883
4884 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4885 "rcv_auth_msg_unmapped_node: payload(11)=0x%x",
4886 (*(uint32_t *)temp));
4887
4888 goto AUTH_Reject;
4889 }
4890 /* Get num_dh */
4891 num_dh = LE_SWAP32(*(uint32_t *)temp) & 0x0000FFFF;
4892
4893 if (num_dh == 0) {
4894 ReasonCode = AUTHRJT_FAILURE;
4895 ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD;
4896
4897 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4898 "rcv_auth_msg_unmapped_node: payload(12)=0x%x",
4899 (*(uint32_t *)temp));
4900
4901 goto AUTH_Reject;
4902 }
4903 for (i = 0; i < num_dh; i++) {
4904 temp += sizeof (uint32_t);
4905 /* Check DHgIDList_g0 */
4906 dh_id[i] = (*(uint32_t *)temp);
4907 }
4908
4909 rc = emlxs_check_dhgp(port, ndlp, dh_id, num_dh, &dhgp_id);
4910
4911 if (rc == 1) {
4912 ReasonCode = AUTHRJT_LOGIC_ERR;
4913 ReasonCodeExplanation = AUTHEXP_DHGROUP_UNUSABLE;
4914
4915 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4916 "rcv_auth_msg_unmapped_node: payload(13)=0x%x",
4917 (*(uint32_t *)temp));
4918
4919 goto AUTH_Reject;
4920 } else if (rc == 2) {
4921 ReasonCode = AUTHRJT_FAILURE;
4922 ReasonCodeExplanation = AUTHEXP_BAD_PAYLOAD;
4923
4924 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4925 "rcv_auth_msg_unmapped_node: payload(14)=0x%x",
4926 (*(uint32_t *)temp));
4927
4928 goto AUTH_Reject;
4929 }
4930 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4931 "rcv_auth_msg_unmapped_node: 0x%x 0x%x 0x%x 0x%x 0x%x",
4932 hash_id, dhgp_id, msg->auth_msg_code, msglen, msg->tran_id);
4933
4934 /*
4935 * since ndlp is the initiator, tran_id is store in
4936 * nlp_auth_tranid_ini
4937 */
4938 node_dhc->nlp_auth_tranid_ini = LE_SWAP32(msg->tran_id);
4939
4940 if (msg->auth_msg_code == AUTH_NEGOTIATE) {
4941
4942 /*
4943 * at this point, we know for sure we received the
4944 * auth-negotiate msg from another entity, so cancel the
4945 * auth-rsp timeout timer if we are expecting it. should
4946 * never happen?
4947 */
4948 node_dhc->nlp_auth_flag = 1;
4949
4950 if (node_dhc->nlp_authrsp_tmo) {
4951 node_dhc->nlp_authrsp_tmo = 0;
4952 }
4953 /*
4954 * If at this point, the host is doing reauthentication
4955 * (reauth heart beat) to this ndlp, then Host should remain
4956 * as the auth initiator, host should reply to the received
4957 * AUTH_Negotiate message with an AUTH_Reject message with
4958 * Reason Code 'Logical Error' and Reason Code Explanation
4959 * 'Authentication Transaction Already Started'.
4960 */
4961 if (node_dhc->nlp_reauth_status ==
4962 NLP_HOST_REAUTH_IN_PROGRESS) {
4963 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
4964 "rcv_auth_msg_unmapped_node: Ht reauth inprgress.");
4965
4966 ReasonCode = AUTHRJT_LOGIC_ERR;
4967 ReasonCodeExplanation = AUTHEXP_AUTHTRAN_STARTED;
4968
4969 goto AUTH_Reject;
4970 }
4971 /* Send back the DHCHAP_Challenge with the proper paramaters */
4972 if (emlxs_issue_dhchap_challenge(port, ndlp, 0, tmp,
4973 LE_SWAP32(msglen),
4974 hash_id, dhgp_id)) {
4975
4976 goto AUTH_Reject;
4977 }
4978 /* setup the proper state */
4979 emlxs_dhc_state(port, ndlp,
4980 NODE_STATE_DHCHAP_CHALLENGE_ISSUE, 0, 0);
4981
4982 } else {
4983 ReasonCode = AUTHRJT_FAILURE;
4984 ReasonCodeExplanation = AUTHEXP_BAD_PROTOCOL;
4985
4986 goto AUTH_Reject;
4987 }
4988
4989 return (node_dhc->state);
4990
4991 AUTH_Reject:
4992
4993 emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_FAILED,
4994 ReasonCode, ReasonCodeExplanation);
4995 (void) emlxs_issue_auth_reject(port, ndlp, 0, 0, ReasonCode,
4996 ReasonCodeExplanation);
4997 emlxs_dhc_auth_complete(port, ndlp, 1);
4998
4999 return (node_dhc->state);
5000
5001 } /* emlxs_rcv_auth_msg_unmapped_node */
5002
5003
5004
5005
5006 /*
5007 * emlxs_hash_vrf for verification only the host is the initiator in
5008 * the routine.
5009 */
5010 /* ARGSUSED */
5011 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)5012 emlxs_hash_vrf(
5013 emlxs_port_t *port,
5014 emlxs_port_dhc_t *port_dhc,
5015 NODELIST *ndlp,
5016 uint32_t tran_id,
5017 union challenge_val un_cval)
5018 {
5019 emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
5020 uint32_t dhgp_id;
5021 uint32_t hash_id;
5022 uint32_t *hash_val;
5023 uint32_t hash_size;
5024 MD5_CTX mdctx;
5025 SHA1_CTX sha1ctx;
5026 uint8_t sha1_digest[20];
5027 uint8_t md5_digest[16];
5028 uint8_t mytran_id = 0x00;
5029
5030 char *remote_key;
5031
5032 tran_id = (AUTH_TRAN_ID_MASK & tran_id);
5033 mytran_id = (uint8_t)(LE_SWAP32(tran_id));
5034
5035
5036 if (ndlp->nlp_DID == FABRIC_DID) {
5037 remote_key = (char *)node_dhc->auth_key.remote_password;
5038 hash_id = node_dhc->hash_id;
5039 dhgp_id = node_dhc->dhgp_id;
5040 } else {
5041 remote_key = (char *)node_dhc->auth_key.remote_password;
5042 hash_id = node_dhc->nlp_auth_hashid;
5043 dhgp_id = node_dhc->nlp_auth_dhgpid;
5044 }
5045
5046 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
5047 "hash_vrf: 0x%x 0x%x 0x%x tran_id=0x%x",
5048 ndlp->nlp_DID, hash_id, dhgp_id, mytran_id);
5049
5050 if (dhgp_id == 0) {
5051 /* NULL DHCHAP */
5052 if (hash_id == AUTH_MD5) {
5053 bzero(&mdctx, sizeof (MD5_CTX));
5054
5055 hash_size = MD5_LEN;
5056
5057 MD5Init(&mdctx);
5058
5059 /* Transaction Identifier T */
5060 MD5Update(&mdctx, (unsigned char *) &mytran_id, 1);
5061
5062 MD5Update(&mdctx, (unsigned char *) remote_key,
5063 node_dhc->auth_key.remote_password_length);
5064
5065 /* Augmented challenge: NULL DHCHAP i.e., Challenge */
5066 MD5Update(&mdctx,
5067 (unsigned char *)&(un_cval.md5.val[0]), MD5_LEN);
5068
5069 MD5Final((uint8_t *)md5_digest, &mdctx);
5070
5071 hash_val = (uint32_t *)kmem_alloc(hash_size,
5072 KM_NOSLEEP);
5073 if (hash_val == NULL) {
5074 return (NULL);
5075 } else {
5076 bcopy((void *)&md5_digest,
5077 (void *)hash_val, MD5_LEN);
5078 }
5079 /*
5080 * emlxs_md5_digest_to_hex((uint8_t *)hash_val,
5081 * output);
5082 */
5083 }
5084 if (hash_id == AUTH_SHA1) {
5085 bzero(&sha1ctx, sizeof (SHA1_CTX));
5086 hash_size = SHA1_LEN;
5087 SHA1Init(&sha1ctx);
5088
5089 SHA1Update(&sha1ctx, (void *)&mytran_id, 1);
5090
5091 SHA1Update(&sha1ctx, (void *)remote_key,
5092 node_dhc->auth_key.remote_password_length);
5093
5094 SHA1Update(&sha1ctx,
5095 (void *)&(un_cval.sha1.val[0]), SHA1_LEN);
5096
5097 SHA1Final((void *)sha1_digest, &sha1ctx);
5098
5099 /*
5100 * emlxs_sha1_digest_to_hex((uint8_t *)hash_val,
5101 * output);
5102 */
5103
5104 hash_val = (uint32_t *)kmem_alloc(hash_size,
5105 KM_NOSLEEP);
5106 if (hash_val == NULL) {
5107 return (NULL);
5108 } else {
5109 bcopy((void *)&sha1_digest,
5110 (void *)hash_val, SHA1_LEN);
5111 }
5112 }
5113 return ((uint32_t *)hash_val);
5114 } else {
5115 /* Verification of bi-dir auth for DH-CHAP group */
5116 /* original challenge is node_dhc->bi_cval[] */
5117 /* session key is node_dhc->ses_key[] */
5118 /* That's IT */
5119 /*
5120 * H(bi_cval || ses_key) = C H(Ti || Km || C) = hash_val
5121 */
5122 if (hash_id == AUTH_MD5) {
5123 bzero(&mdctx, sizeof (MD5_CTX));
5124 hash_size = MD5_LEN;
5125
5126 MD5Init(&mdctx);
5127
5128 MD5Update(&mdctx,
5129 (void *)&(un_cval.md5.val[0]), MD5_LEN);
5130
5131 if (ndlp->nlp_DID == FABRIC_DID) {
5132 MD5Update(&mdctx,
5133 (void *)&node_dhc->ses_key[0],
5134 node_dhc->seskey_len);
5135 } else {
5136 /* ses_key is obtained in emlxs_hash_rsp */
5137 MD5Update(&mdctx,
5138 (void *)&node_dhc->nlp_auth_misc.ses_key[0],
5139 node_dhc->nlp_auth_misc.seskey_len);
5140 }
5141
5142 MD5Final((void *)md5_digest, &mdctx);
5143
5144 MD5Init(&mdctx);
5145
5146 MD5Update(&mdctx, (void *)&mytran_id, 1);
5147
5148 MD5Update(&mdctx, (void *)remote_key,
5149 node_dhc->auth_key.remote_password_length);
5150
5151 MD5Update(&mdctx, (void *)md5_digest, MD5_LEN);
5152
5153 MD5Final((void *)md5_digest, &mdctx);
5154
5155 hash_val = (uint32_t *)kmem_alloc(hash_size,
5156 KM_NOSLEEP);
5157 if (hash_val == NULL) {
5158 return (NULL);
5159 } else {
5160 bcopy((void *)&md5_digest,
5161 (void *)hash_val, MD5_LEN);
5162 }
5163 }
5164 if (hash_id == AUTH_SHA1) {
5165 bzero(&sha1ctx, sizeof (SHA1_CTX));
5166 hash_size = SHA1_LEN;
5167
5168 SHA1Init(&sha1ctx);
5169
5170 SHA1Update(&sha1ctx,
5171 (void *)&(un_cval.sha1.val[0]), SHA1_LEN);
5172
5173 if (ndlp->nlp_DID == FABRIC_DID) {
5174 SHA1Update(&sha1ctx,
5175 (void *)&node_dhc->ses_key[0],
5176 node_dhc->seskey_len);
5177 } else {
5178 /* ses_key was obtained in emlxs_hash_rsp */
5179 SHA1Update(&sha1ctx,
5180 (void *)&node_dhc->nlp_auth_misc.ses_key[0],
5181 node_dhc->nlp_auth_misc.seskey_len);
5182 }
5183
5184 SHA1Final((void *)sha1_digest, &sha1ctx);
5185
5186 SHA1Init(&sha1ctx);
5187
5188 SHA1Update(&sha1ctx, (void *)&mytran_id, 1);
5189
5190 SHA1Update(&sha1ctx, (void *)remote_key,
5191 node_dhc->auth_key.remote_password_length);
5192
5193 SHA1Update(&sha1ctx, (void *)sha1_digest, SHA1_LEN);
5194
5195 SHA1Final((void *)sha1_digest, &sha1ctx);
5196
5197 hash_val = (uint32_t *)kmem_alloc(hash_size,
5198 KM_NOSLEEP);
5199 if (hash_val == NULL) {
5200 return (NULL);
5201 } else {
5202 bcopy((void *)&sha1_digest,
5203 (void *)hash_val, SHA1_LEN);
5204 }
5205 }
5206 return ((uint32_t *)hash_val);
5207 }
5208
5209 } /* emlxs_hash_vrf */
5210
5211
5212 /*
5213 * If dhval == NULL, NULL DHCHAP else, DHCHAP group.
5214 *
5215 * This routine is used by the auth transaction initiator (Who does the
5216 * auth-negotiate) to calculate the R1 (response) based on
5217 * the dh value it received, its own random private key, the challenge it
5218 * received, and Transaction id, as well as the password
5219 * associated with this very initiator in the auth pair.
5220 */
5221 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)5222 emlxs_hash_rsp(
5223 emlxs_port_t *port,
5224 emlxs_port_dhc_t *port_dhc,
5225 NODELIST *ndlp,
5226 uint32_t tran_id,
5227 union challenge_val un_cval,
5228 uint8_t *dhval,
5229 uint32_t dhvallen)
5230 {
5231 emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
5232 uint32_t dhgp_id;
5233 uint32_t hash_id;
5234 uint32_t *hash_val;
5235 uint32_t hash_size;
5236 MD5_CTX mdctx;
5237 SHA1_CTX sha1ctx;
5238 uint8_t sha1_digest[20];
5239 uint8_t md5_digest[16];
5240 uint8_t Cai[20];
5241 uint8_t mytran_id = 0x00;
5242 char *mykey;
5243 BIG_ERR_CODE err = BIG_OK;
5244
5245 if (ndlp->nlp_DID == FABRIC_DID) {
5246 hash_id = node_dhc->hash_id;
5247 dhgp_id = node_dhc->dhgp_id;
5248 } else {
5249 hash_id = node_dhc->nlp_auth_hashid;
5250 dhgp_id = node_dhc->nlp_auth_dhgpid;
5251 }
5252
5253 tran_id = (AUTH_TRAN_ID_MASK & tran_id);
5254 mytran_id = (uint8_t)(LE_SWAP32(tran_id));
5255
5256 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
5257 "hash_rsp: 0x%x 0x%x 0x%x 0x%x dhvallen=0x%x",
5258 ndlp->nlp_DID, hash_id, dhgp_id, mytran_id, dhvallen);
5259
5260 if (ndlp->nlp_DID == FABRIC_DID) {
5261 mykey = (char *)node_dhc->auth_key.local_password;
5262
5263 } else {
5264 mykey = (char *)node_dhc->auth_key.local_password;
5265 }
5266
5267 if (dhval == NULL) {
5268 /* NULL DHCHAP */
5269 if (hash_id == AUTH_MD5) {
5270 bzero(&mdctx, sizeof (MD5_CTX));
5271 hash_size = MD5_LEN;
5272
5273 MD5Init(&mdctx);
5274
5275 MD5Update(&mdctx, (unsigned char *)&mytran_id, 1);
5276
5277 MD5Update(&mdctx, (unsigned char *)mykey,
5278 node_dhc->auth_key.local_password_length);
5279
5280 MD5Update(&mdctx,
5281 (unsigned char *)&(un_cval.md5.val[0]),
5282 MD5_LEN);
5283
5284 MD5Final((uint8_t *)md5_digest, &mdctx);
5285
5286 hash_val = (uint32_t *)kmem_alloc(hash_size,
5287 KM_NOSLEEP);
5288 if (hash_val == NULL) {
5289 return (NULL);
5290 } else {
5291 bcopy((void *)&md5_digest,
5292 (void *)hash_val, MD5_LEN);
5293 }
5294
5295 /*
5296 * emlxs_md5_digest_to_hex((uint8_t *)hash_val,
5297 * output);
5298 */
5299
5300 }
5301 if (hash_id == AUTH_SHA1) {
5302 bzero(&sha1ctx, sizeof (SHA1_CTX));
5303 hash_size = SHA1_LEN;
5304 SHA1Init(&sha1ctx);
5305
5306 SHA1Update(&sha1ctx, (void *)&mytran_id, 1);
5307
5308 SHA1Update(&sha1ctx, (void *)mykey,
5309 node_dhc->auth_key.local_password_length);
5310
5311 SHA1Update(&sha1ctx,
5312 (void *)&(un_cval.sha1.val[0]), SHA1_LEN);
5313
5314 SHA1Final((void *)sha1_digest, &sha1ctx);
5315
5316 /*
5317 * emlxs_sha1_digest_to_hex((uint8_t *)hash_val,
5318 * output);
5319 */
5320
5321 hash_val = (uint32_t *)kmem_alloc(hash_size,
5322 KM_NOSLEEP);
5323 if (hash_val == NULL) {
5324 return (NULL);
5325 } else {
5326 bcopy((void *)&sha1_digest,
5327 (void *)hash_val, SHA1_LEN);
5328 }
5329 }
5330 return ((uint32_t *)hash_val);
5331 } else {
5332
5333 /* process DH grops */
5334 /*
5335 * calculate interm hash value Ca1 Ca1 = H(C1 || (g^x mod
5336 * p)^y mod p) in which C1 is the challenge received. g^x mod
5337 * p is the dhval received y is the random number in 16 bytes
5338 * for MD5, 20 bytes for SHA1 p is hardcoded value based on
5339 * different DH groups.
5340 *
5341 * To calculate hash value R1 R1 = H (Ti || Kn || Cai) in which
5342 * Ti is the transaction identifier Kn is the shared secret.
5343 * Cai is the result from interm hash.
5344 *
5345 * g^y mod p is reserved in port_dhc as pubkey (public key).for
5346 * bi-dir challenge is another random number. y is prikey
5347 * (private key). ((g^x mod p)^y mod p) is sekey (session
5348 * key)
5349 */
5350 err = emlxs_interm_hash(port, port_dhc, ndlp,
5351 (void *)&Cai, tran_id,
5352 un_cval, dhval, &dhvallen);
5353
5354 if (err != BIG_OK) {
5355 return (NULL);
5356 }
5357 if (hash_id == AUTH_MD5) {
5358 bzero(&mdctx, sizeof (MD5_CTX));
5359 hash_size = MD5_LEN;
5360
5361 MD5Init(&mdctx);
5362
5363 MD5Update(&mdctx, (unsigned char *)&mytran_id, 1);
5364
5365 MD5Update(&mdctx, (unsigned char *)mykey,
5366 node_dhc->auth_key.local_password_length);
5367
5368 MD5Update(&mdctx, (unsigned char *)Cai, MD5_LEN);
5369
5370 MD5Final((uint8_t *)md5_digest, &mdctx);
5371
5372 hash_val = (uint32_t *)kmem_alloc(hash_size,
5373 KM_NOSLEEP);
5374 if (hash_val == NULL) {
5375 return (NULL);
5376 } else {
5377 bcopy((void *)&md5_digest,
5378 (void *)hash_val, MD5_LEN);
5379 }
5380 }
5381 if (hash_id == AUTH_SHA1) {
5382 bzero(&sha1ctx, sizeof (SHA1_CTX));
5383 hash_size = SHA1_LEN;
5384
5385 SHA1Init(&sha1ctx);
5386
5387 SHA1Update(&sha1ctx, (void *)&mytran_id, 1);
5388
5389 SHA1Update(&sha1ctx, (void *)mykey,
5390 node_dhc->auth_key.local_password_length);
5391
5392 SHA1Update(&sha1ctx, (void *)&Cai[0], SHA1_LEN);
5393
5394 SHA1Final((void *)sha1_digest, &sha1ctx);
5395
5396 hash_val = (uint32_t *)kmem_alloc(hash_size,
5397 KM_NOSLEEP);
5398 if (hash_val == NULL) {
5399 return (NULL);
5400 } else {
5401 bcopy((void *)&sha1_digest,
5402 (void *)hash_val, SHA1_LEN);
5403 }
5404 }
5405 return ((uint32_t *)hash_val);
5406 }
5407
5408 } /* emlxs_hash_rsp */
5409
5410
5411 /*
5412 * To get the augmented challenge Cai Stored in hash_val
5413 *
5414 * Cai = Hash (C1 || ((g^x mod p)^y mod p)) = Hash (C1 || (g^(x*y) mod p)
5415 *
5416 * C1:challenge received from the remote entity (g^x mod p): dh val
5417 * received from the remote entity (remote entity's pubkey) y:
5418 * random private key from the local entity Hash: hash function used in
5419 * agreement. (g^(x*y) mod p): shared session key (aka
5420 * shared secret) (g^y mod p): local entity's pubkey
5421 */
5422 /* ARGSUSED */
5423 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)5424 emlxs_interm_hash(
5425 emlxs_port_t *port,
5426 emlxs_port_dhc_t *port_dhc,
5427 NODELIST *ndlp,
5428 void *hash_val,
5429 uint32_t tran_id,
5430 union challenge_val un_cval,
5431 uint8_t *dhval,
5432 uint32_t *dhvallen)
5433 {
5434 emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
5435 uint32_t dhgp_id;
5436 uint32_t hash_id;
5437 MD5_CTX mdctx;
5438 SHA1_CTX sha1ctx;
5439 uint8_t sha1_digest[20];
5440 uint8_t md5_digest[16];
5441 uint32_t hash_size;
5442 BIG_ERR_CODE err = BIG_OK;
5443
5444 if (ndlp->nlp_DID == FABRIC_DID) {
5445 hash_id = node_dhc->hash_id;
5446 dhgp_id = node_dhc->dhgp_id;
5447 } else {
5448 hash_id = node_dhc->nlp_auth_hashid;
5449 dhgp_id = node_dhc->nlp_auth_dhgpid;
5450 }
5451
5452 if (hash_id == AUTH_MD5) {
5453 bzero(&mdctx, sizeof (MD5_CTX));
5454 hash_size = MD5_LEN;
5455 MD5Init(&mdctx);
5456 MD5Update(&mdctx,
5457 (unsigned char *)&(un_cval.md5.val[0]), MD5_LEN);
5458
5459 /*
5460 * get the pub key (g^y mod p) and session key (g^(x*y) mod
5461 * p) and stored them in the partner's ndlp structure
5462 */
5463 err = emlxs_BIGNUM_get_pubkey(port, port_dhc, ndlp,
5464 dhval, dhvallen, hash_size, dhgp_id);
5465
5466 if (err != BIG_OK) {
5467 return (err);
5468 }
5469 if (ndlp->nlp_DID == FABRIC_DID) {
5470 MD5Update(&mdctx,
5471 (unsigned char *)&node_dhc->ses_key[0],
5472 node_dhc->seskey_len);
5473 } else {
5474 MD5Update(&mdctx,
5475 (unsigned char *)&node_dhc->nlp_auth_misc.ses_key[0],
5476 node_dhc->nlp_auth_misc.seskey_len);
5477 }
5478
5479 MD5Final((uint8_t *)md5_digest, &mdctx);
5480
5481 bcopy((void *)&md5_digest, (void *)hash_val, MD5_LEN);
5482 }
5483 if (hash_id == AUTH_SHA1) {
5484 bzero(&sha1ctx, sizeof (SHA1_CTX));
5485
5486 hash_size = SHA1_LEN;
5487
5488 SHA1Init(&sha1ctx);
5489
5490 SHA1Update(&sha1ctx, (void *)&(un_cval.sha1.val[0]), SHA1_LEN);
5491
5492 /* get the pub key and session key */
5493 err = emlxs_BIGNUM_get_pubkey(port, port_dhc, ndlp,
5494 dhval, dhvallen, hash_size, dhgp_id);
5495
5496 if (err != BIG_OK) {
5497 return (err);
5498 }
5499 if (ndlp->nlp_DID == FABRIC_DID) {
5500 SHA1Update(&sha1ctx, (void *)&node_dhc->ses_key[0],
5501 node_dhc->seskey_len);
5502 } else {
5503 SHA1Update(&sha1ctx,
5504 (void *)&node_dhc->nlp_auth_misc.ses_key[0],
5505 node_dhc->nlp_auth_misc.seskey_len);
5506 }
5507
5508 SHA1Final((void *)sha1_digest, &sha1ctx);
5509
5510 bcopy((void *)&sha1_digest, (void *)hash_val, SHA1_LEN);
5511 }
5512 return (err);
5513
5514 } /* emlxs_interm_hash */
5515
5516 /*
5517 * This routine get the pubkey and session key. these pubkey and session
5518 * key are stored in the partner's ndlp structure.
5519 */
5520 /* ARGSUSED */
5521 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)5522 emlxs_BIGNUM_get_pubkey(
5523 emlxs_port_t *port,
5524 emlxs_port_dhc_t *port_dhc,
5525 NODELIST *ndlp,
5526 uint8_t *dhval,
5527 uint32_t *dhvallen,
5528 uint32_t hash_size,
5529 uint32_t dhgp_id)
5530 {
5531 emlxs_hba_t *hba = HBA;
5532
5533 BIGNUM a, e, n, result;
5534 uint32_t plen;
5535 uint8_t random_number[20];
5536 unsigned char *tmp = NULL;
5537 BIGNUM g, result1;
5538
5539 #ifdef BIGNUM_CHUNK_32
5540 uint8_t gen[] = {0x00, 0x00, 0x00, 0x02};
5541 #else
5542 uint8_t gen[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02};
5543 #endif /* BIGNUM_CHUNK_32 */
5544
5545 emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
5546 BIG_ERR_CODE err = BIG_OK;
5547
5548 /*
5549 * compute a^e mod n assume a < n, n odd, result->value at least as
5550 * long as n->value.
5551 *
5552 * a is the public key received from responder. e is the private key
5553 * generated by me. n is the wellknown modulus.
5554 */
5555
5556 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
5557 "BIGNUM_get_pubkey: 0x%x 0x%x 0x%x 0x%x",
5558 ndlp->nlp_DID, *dhvallen, hash_size, dhgp_id);
5559
5560 /* size should be in the unit of (BIG_CHUNK_TYPE) words */
5561 if (big_init(&a, CHARLEN2BIGNUMLEN(*dhvallen)) != BIG_OK) {
5562 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5563 "BIGNUM_get_pubkey: big_init failed. a size=%d",
5564 CHARLEN2BIGNUMLEN(*dhvallen));
5565
5566 err = BIG_NO_MEM;
5567 return (err);
5568 }
5569 /* a: (g^x mod p) */
5570 /*
5571 * dhval is in big-endian format. This call converts from
5572 * byte-big-endian format to big number format (words in little
5573 * endian order, but bytes within the words big endian)
5574 */
5575 bytestring2bignum(&a, (unsigned char *)dhval, *dhvallen);
5576
5577 if (big_init(&e, CHARLEN2BIGNUMLEN(hash_size)) != BIG_OK) {
5578 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5579 "BIGNUM_get_pubkey: big_init failed. e size=%d",
5580 CHARLEN2BIGNUMLEN(hash_size));
5581
5582 err = BIG_NO_MEM;
5583 goto ret1;
5584 }
5585 #ifdef RAND
5586
5587 bzero(&random_number, hash_size);
5588
5589 /* to get random private key: y */
5590 /* remember y is short lived private key */
5591 if (hba->rdn_flag == 1) {
5592 emlxs_get_random_bytes(ndlp, random_number, 20);
5593 } else {
5594 (void) random_get_pseudo_bytes(random_number, hash_size);
5595 }
5596
5597 /* e: y */
5598 bytestring2bignum(&e, (unsigned char *)random_number, hash_size);
5599
5600 #endif /* RAND */
5601
5602 #ifdef MYRAND
5603 bytestring2bignum(&e, (unsigned char *)myrand, hash_size);
5604
5605 printf("myrand random_number as Y ================\n");
5606 for (i = 0; i < 5; i++) {
5607 for (j = 0; j < 4; j++) {
5608 printf("%x", myrand[(i * 4) + j]);
5609 }
5610 printf("\n");
5611 }
5612 #endif /* MYRAND */
5613
5614 switch (dhgp_id) {
5615 case GROUP_1024:
5616 plen = 128;
5617 tmp = dhgp1_pVal;
5618 break;
5619
5620 case GROUP_1280:
5621 plen = 160;
5622 tmp = dhgp2_pVal;
5623 break;
5624
5625 case GROUP_1536:
5626 plen = 192;
5627 tmp = dhgp3_pVal;
5628 break;
5629
5630 case GROUP_2048:
5631 plen = 256;
5632 tmp = dhgp4_pVal;
5633 break;
5634 }
5635
5636 if (big_init(&n, CHARLEN2BIGNUMLEN(plen)) != BIG_OK) {
5637 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5638 "BIGNUM_get_pubkey: big_init failed. n size=%d",
5639 CHARLEN2BIGNUMLEN(plen));
5640 err = BIG_NO_MEM;
5641 goto ret2;
5642 }
5643 bytestring2bignum(&n, (unsigned char *)tmp, plen);
5644
5645 if (big_init(&result, CHARLEN2BIGNUMLEN(512)) != BIG_OK) {
5646 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5647 "BIGNUM_get_pubkey: big_init failed. result size=%d",
5648 CHARLEN2BIGNUMLEN(512));
5649
5650 err = BIG_NO_MEM;
5651 goto ret3;
5652 }
5653 if (big_cmp_abs(&a, &n) > 0) {
5654 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5655 "BIGNUM_get_pubkey: big_cmp_abs error.");
5656 err = BIG_GENERAL_ERR;
5657 goto ret4;
5658 }
5659 /* perform computation on big numbers to get seskey */
5660 /* a^e mod n */
5661 /* i.e., (g^x mod p)^y mod p */
5662
5663 if (big_modexp(&result, &a, &e, &n, NULL) != BIG_OK) {
5664 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5665 "BIGNUM_get_pubkey: big_modexp result error");
5666 err = BIG_NO_MEM;
5667 goto ret4;
5668 }
5669 /* convert big number ses_key to bytestring */
5670 if (ndlp->nlp_DID == FABRIC_DID) {
5671 /*
5672 * This call converts from big number format to
5673 * byte-big-endian format. big number format is words in
5674 * little endian order, but bytes within words in native byte
5675 * order
5676 */
5677 bignum2bytestring(node_dhc->ses_key, &result,
5678 sizeof (BIG_CHUNK_TYPE) * (result.len));
5679 node_dhc->seskey_len = sizeof (BIG_CHUNK_TYPE) * (result.len);
5680
5681 /* we can store another copy in ndlp */
5682 bignum2bytestring(node_dhc->nlp_auth_misc.ses_key, &result,
5683 sizeof (BIG_CHUNK_TYPE) * (result.len));
5684 node_dhc->nlp_auth_misc.seskey_len =
5685 sizeof (BIG_CHUNK_TYPE) * (result.len);
5686 } else {
5687 /* for end-to-end auth */
5688 bignum2bytestring(node_dhc->nlp_auth_misc.ses_key, &result,
5689 sizeof (BIG_CHUNK_TYPE) * (result.len));
5690 node_dhc->nlp_auth_misc.seskey_len =
5691 sizeof (BIG_CHUNK_TYPE) * (result.len);
5692 }
5693
5694 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
5695 "BIGNUM_get_pubkey: after seskey cal: 0x%x 0x%x 0x%x",
5696 node_dhc->nlp_auth_misc.seskey_len, result.size, result.len);
5697
5698
5699 /* to get pub_key: g^y mod p, g is 2 */
5700
5701 if (big_init(&g, 1) != BIG_OK) {
5702 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5703 "BIGNUM_get_pubkey: big_init failed. g size=1");
5704
5705 err = BIG_NO_MEM;
5706 goto ret4;
5707 }
5708 if (big_init(&result1, CHARLEN2BIGNUMLEN(512)) != BIG_OK) {
5709 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5710 "BIGNUM_get_pubkey: big_init failed. result1 size=%d",
5711 CHARLEN2BIGNUMLEN(512));
5712 err = BIG_NO_MEM;
5713 goto ret5;
5714 }
5715
5716 bytestring2bignum(&g,
5717 (unsigned char *)&gen, sizeof (BIG_CHUNK_TYPE));
5718
5719 if (big_modexp(&result1, &g, &e, &n, NULL) != BIG_OK) {
5720 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5721 "BIGNUM_get_pubkey: big_modexp result1 error");
5722 err = BIG_NO_MEM;
5723 goto ret6;
5724 }
5725 /* convert big number pub_key to bytestring */
5726 if (ndlp->nlp_DID == FABRIC_DID) {
5727
5728 bignum2bytestring(node_dhc->pub_key, &result1,
5729 sizeof (BIG_CHUNK_TYPE) * (result1.len));
5730 node_dhc->pubkey_len = (result1.len) * sizeof (BIG_CHUNK_TYPE);
5731
5732 /* save another copy in ndlp */
5733 bignum2bytestring(node_dhc->nlp_auth_misc.pub_key, &result1,
5734 sizeof (BIG_CHUNK_TYPE) * (result1.len));
5735 node_dhc->nlp_auth_misc.pubkey_len =
5736 (result1.len) * sizeof (BIG_CHUNK_TYPE);
5737
5738 } else {
5739 /* for end-to-end auth */
5740 bignum2bytestring(node_dhc->nlp_auth_misc.pub_key, &result1,
5741 sizeof (BIG_CHUNK_TYPE) * (result1.len));
5742 node_dhc->nlp_auth_misc.pubkey_len =
5743 (result1.len) * sizeof (BIG_CHUNK_TYPE);
5744 }
5745
5746 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
5747 "BIGNUM_get_pubkey: after pubkey cal: 0x%x 0x%x 0x%x",
5748 node_dhc->nlp_auth_misc.pubkey_len, result1.size, result1.len);
5749
5750
5751 ret6:
5752 big_finish(&result1);
5753 ret5:
5754 big_finish(&g);
5755 ret4:
5756 big_finish(&result);
5757 ret3:
5758 big_finish(&n);
5759 ret2:
5760 big_finish(&e);
5761 ret1:
5762 big_finish(&a);
5763
5764 return (err);
5765
5766 } /* emlxs_BIGNUM_get_pubkey */
5767
5768
5769 /*
5770 * g^x mod p x is the priv_key g and p are wellknow based on dhgp_id
5771 */
5772 /* ARGSUSED */
5773 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)5774 emlxs_BIGNUM_get_dhval(
5775 emlxs_port_t *port,
5776 emlxs_port_dhc_t *port_dhc,
5777 NODELIST *ndlp,
5778 uint8_t *dhval,
5779 uint32_t *dhval_len,
5780 uint32_t dhgp_id,
5781 uint8_t *priv_key,
5782 uint32_t privkey_len)
5783 {
5784 emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
5785 BIGNUM g, e, n, result1;
5786 uint32_t plen;
5787 unsigned char *tmp = NULL;
5788
5789 #ifdef BIGNUM_CHUNK_32
5790 uint8_t gen[] = {0x00, 0x00, 0x00, 0x02};
5791 #else
5792 uint8_t gen[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02};
5793 #endif /* BIGNUM_CHUNK_32 */
5794
5795 BIG_ERR_CODE err = BIG_OK;
5796
5797 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
5798 "BIGNUM_get_dhval: did=0x%x privkey_len=0x%x dhgp_id=0x%x",
5799 ndlp->nlp_DID, privkey_len, dhgp_id);
5800
5801 if (big_init(&result1, CHARLEN2BIGNUMLEN(512)) != BIG_OK) {
5802 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5803 "BIGNUM_get_dhval: big_init failed. result1 size=%d",
5804 CHARLEN2BIGNUMLEN(512));
5805
5806 err = BIG_NO_MEM;
5807 return (err);
5808 }
5809 if (big_init(&g, 1) != BIG_OK) {
5810 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5811 "BIGNUM_get_dhval: big_init failed. g size=1");
5812
5813 err = BIG_NO_MEM;
5814 goto ret1;
5815 }
5816 /* get g */
5817 bytestring2bignum(&g, (unsigned char *)gen, sizeof (BIG_CHUNK_TYPE));
5818
5819 if (big_init(&e, CHARLEN2BIGNUMLEN(privkey_len)) != BIG_OK) {
5820 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5821 "BIGNUM_get_dhval: big_init failed. e size=%d",
5822 CHARLEN2BIGNUMLEN(privkey_len));
5823
5824 err = BIG_NO_MEM;
5825 goto ret2;
5826 }
5827 /* get x */
5828 bytestring2bignum(&e, (unsigned char *)priv_key, privkey_len);
5829
5830 switch (dhgp_id) {
5831 case GROUP_1024:
5832 plen = 128;
5833 tmp = dhgp1_pVal;
5834 break;
5835
5836 case GROUP_1280:
5837 plen = 160;
5838 tmp = dhgp2_pVal;
5839 break;
5840
5841 case GROUP_1536:
5842 plen = 192;
5843 tmp = dhgp3_pVal;
5844 break;
5845
5846 case GROUP_2048:
5847 plen = 256;
5848 tmp = dhgp4_pVal;
5849 break;
5850 }
5851
5852 if (big_init(&n, CHARLEN2BIGNUMLEN(plen)) != BIG_OK) {
5853 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5854 "BIGNUM_get_dhval: big_init failed. n size=%d",
5855 CHARLEN2BIGNUMLEN(plen));
5856
5857 err = BIG_NO_MEM;
5858 goto ret3;
5859 }
5860 /* get p */
5861 bytestring2bignum(&n, (unsigned char *)tmp, plen);
5862
5863 /* to cal: (g^x mod p) */
5864 if (big_modexp(&result1, &g, &e, &n, NULL) != BIG_OK) {
5865 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5866 "BIGNUM_get_dhval: big_modexp result1 error");
5867
5868 err = BIG_GENERAL_ERR;
5869 goto ret4;
5870 }
5871 /* convert big number pub_key to bytestring */
5872 if (ndlp->nlp_DID == FABRIC_DID) {
5873 bignum2bytestring(node_dhc->hrsp_pub_key, &result1,
5874 sizeof (BIG_CHUNK_TYPE) * (result1.len));
5875 node_dhc->hrsp_pubkey_len =
5876 (result1.len) * sizeof (BIG_CHUNK_TYPE);
5877
5878 /* save another copy in partner's ndlp */
5879 bignum2bytestring(node_dhc->nlp_auth_misc.hrsp_pub_key,
5880 &result1,
5881 sizeof (BIG_CHUNK_TYPE) * (result1.len));
5882
5883 node_dhc->nlp_auth_misc.hrsp_pubkey_len =
5884 (result1.len) * sizeof (BIG_CHUNK_TYPE);
5885 } else {
5886 bignum2bytestring(node_dhc->nlp_auth_misc.hrsp_pub_key,
5887 &result1,
5888 sizeof (BIG_CHUNK_TYPE) * (result1.len));
5889 node_dhc->nlp_auth_misc.hrsp_pubkey_len =
5890 (result1.len) * sizeof (BIG_CHUNK_TYPE);
5891 }
5892
5893
5894 if (ndlp->nlp_DID == FABRIC_DID) {
5895 bcopy((void *)node_dhc->hrsp_pub_key, (void *)dhval,
5896 node_dhc->hrsp_pubkey_len);
5897 } else {
5898 bcopy((void *)node_dhc->nlp_auth_misc.hrsp_pub_key,
5899 (void *)dhval,
5900 node_dhc->nlp_auth_misc.hrsp_pubkey_len);
5901 }
5902
5903 *(uint32_t *)dhval_len = (result1.len) * sizeof (BIG_CHUNK_TYPE);
5904
5905
5906 ret4:
5907 big_finish(&result1);
5908 ret3:
5909 big_finish(&e);
5910 ret2:
5911 big_finish(&n);
5912 ret1:
5913 big_finish(&g);
5914
5915 return (err);
5916
5917 } /* emlxs_BIGNUM_get_dhval */
5918
5919
5920 /*
5921 * to get ((g^y mod p)^x mod p) a^e mod n
5922 */
5923 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)5924 emlxs_BIGNUM_pubkey(
5925 emlxs_port_t *port,
5926 void *pubkey,
5927 uint8_t *dhval, /* g^y mod p */
5928 uint32_t dhvallen,
5929 uint8_t *key, /* x */
5930 uint32_t key_size,
5931 uint32_t dhgp_id,
5932 uint32_t *pubkeylen)
5933 {
5934 BIGNUM a, e, n, result;
5935 uint32_t plen;
5936 unsigned char *tmp = NULL;
5937 BIG_ERR_CODE err = BIG_OK;
5938
5939 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
5940 "BIGNUM_pubkey: dhvallen=0x%x dhgp_id=0x%x",
5941 dhvallen, dhgp_id);
5942
5943 if (big_init(&a, CHARLEN2BIGNUMLEN(dhvallen)) != BIG_OK) {
5944 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5945 "BIGNUM_pubkey: big_init failed. a size=%d",
5946 CHARLEN2BIGNUMLEN(dhvallen));
5947
5948 err = BIG_NO_MEM;
5949 return (err);
5950 }
5951 /* get g^y mod p */
5952 bytestring2bignum(&a, (unsigned char *)dhval, dhvallen);
5953
5954 if (big_init(&e, CHARLEN2BIGNUMLEN(key_size)) != BIG_OK) {
5955 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5956 "BIGNUM_pubkey: big_init failed. e size=%d",
5957 CHARLEN2BIGNUMLEN(key_size));
5958
5959 err = BIG_NO_MEM;
5960 goto ret1;
5961 }
5962 /* get x */
5963 bytestring2bignum(&e, (unsigned char *)key, key_size);
5964
5965 switch (dhgp_id) {
5966 case GROUP_1024:
5967 plen = 128;
5968 tmp = dhgp1_pVal;
5969 break;
5970
5971 case GROUP_1280:
5972 plen = 160;
5973 tmp = dhgp2_pVal;
5974 break;
5975
5976 case GROUP_1536:
5977 plen = 192;
5978 tmp = dhgp3_pVal;
5979 break;
5980
5981 case GROUP_2048:
5982 plen = 256;
5983 tmp = dhgp4_pVal;
5984 break;
5985 }
5986
5987 if (big_init(&n, CHARLEN2BIGNUMLEN(plen)) != BIG_OK) {
5988 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5989 "BIGNUM_pubkey: big_init failed. n size=%d",
5990 CHARLEN2BIGNUMLEN(plen));
5991
5992 err = BIG_NO_MEM;
5993 goto ret2;
5994 }
5995 bytestring2bignum(&n, (unsigned char *)tmp, plen);
5996
5997 if (big_init(&result, CHARLEN2BIGNUMLEN(512)) != BIG_OK) {
5998 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
5999 "BIGNUM_pubkey: big_init failed. result size=%d",
6000 CHARLEN2BIGNUMLEN(512));
6001
6002 err = BIG_NO_MEM;
6003 goto ret3;
6004 }
6005 if (big_cmp_abs(&a, &n) > 0) {
6006 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
6007 "BIGNUM_pubkey: big_cmp_abs error");
6008
6009 err = BIG_GENERAL_ERR;
6010 goto ret4;
6011 }
6012 if (big_modexp(&result, &a, &e, &n, NULL) != BIG_OK) {
6013 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
6014 "BIGNUM_pubkey: big_modexp result error");
6015
6016 err = BIG_NO_MEM;
6017 goto ret4;
6018 }
6019 bignum2bytestring(pubkey, &result,
6020 sizeof (BIG_CHUNK_TYPE) * (result.len));
6021 *pubkeylen = sizeof (BIG_CHUNK_TYPE) * (result.len);
6022
6023 /* This pubkey is actually session key */
6024
6025 ret4:
6026 big_finish(&result);
6027 ret3:
6028 big_finish(&n);
6029 ret2:
6030 big_finish(&e);
6031 ret1:
6032 big_finish(&a);
6033
6034 return (err);
6035
6036 } /* emlxs_BIGNUM_pubkey */
6037
6038
6039 /*
6040 * key: x dhval: (g^y mod p) tran_id: Ti bi_cval: C2 hash_id: H dhgp_id: p/g
6041 *
6042 * Cai = H (C2 || ((g^y mod p)^x mod p) )
6043 *
6044 */
6045 /* ARGSUSED */
6046 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)6047 emlxs_hash_Cai(
6048 emlxs_port_t *port,
6049 emlxs_port_dhc_t *port_dhc,
6050 NODELIST *ndlp,
6051 void *Cai,
6052 uint32_t hash_id,
6053 uint32_t dhgp_id,
6054 uint32_t tran_id,
6055 uint8_t *cval,
6056 uint32_t cval_len,
6057 uint8_t *key,
6058 uint8_t *dhval,
6059 uint32_t dhvallen)
6060 {
6061 emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
6062 MD5_CTX mdctx;
6063 SHA1_CTX sha1ctx;
6064 uint8_t sha1_digest[20];
6065 uint8_t md5_digest[16];
6066 uint8_t pubkey[512];
6067 uint32_t pubkey_len = 0;
6068 uint32_t key_size;
6069 BIG_ERR_CODE err = BIG_OK;
6070
6071 key_size = cval_len;
6072 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
6073 "hash_Cai: 0x%x 0x%x 0x%x 0x%x 0x%x",
6074 ndlp->nlp_DID, hash_id, dhgp_id, tran_id, dhvallen);
6075
6076 if (hash_id == AUTH_MD5) {
6077 bzero(&mdctx, sizeof (MD5_CTX));
6078 MD5Init(&mdctx);
6079 MD5Update(&mdctx, (unsigned char *)cval, cval_len);
6080
6081 /* this pubkey obtained is actually the session key */
6082 /*
6083 * pubkey: ((g^y mod p)^x mod p)
6084 */
6085 err = emlxs_BIGNUM_pubkey(port, pubkey, dhval, dhvallen,
6086 key, key_size, dhgp_id, &pubkey_len);
6087
6088 if (err != BIG_OK) {
6089 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
6090 "hash_Cai: MD5 BIGNUM_pubkey error: 0x%x",
6091 err);
6092
6093 err = BIG_GENERAL_ERR;
6094 return (err);
6095 }
6096 if (pubkey_len == 0) {
6097 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
6098 "hash_Cai: MD5 BIGNUM_pubkey error: len=0");
6099
6100 err = BIG_GENERAL_ERR;
6101 return (err);
6102 }
6103 if (ndlp->nlp_DID == FABRIC_DID) {
6104 bcopy((void *)pubkey,
6105 (void *)node_dhc->hrsp_ses_key, pubkey_len);
6106 node_dhc->hrsp_seskey_len = pubkey_len;
6107
6108 /* store extra copy */
6109 bcopy((void *)pubkey,
6110 (void *)node_dhc->nlp_auth_misc.hrsp_ses_key,
6111 pubkey_len);
6112 node_dhc->nlp_auth_misc.hrsp_seskey_len = pubkey_len;
6113
6114 } else {
6115 bcopy((void *)pubkey,
6116 (void *)node_dhc->nlp_auth_misc.hrsp_ses_key,
6117 pubkey_len);
6118 node_dhc->nlp_auth_misc.hrsp_seskey_len = pubkey_len;
6119 }
6120
6121 MD5Update(&mdctx, (unsigned char *)pubkey, pubkey_len);
6122 MD5Final((uint8_t *)md5_digest, &mdctx);
6123 bcopy((void *)&md5_digest, (void *)Cai, MD5_LEN);
6124 }
6125 if (hash_id == AUTH_SHA1) {
6126 bzero(&sha1ctx, sizeof (SHA1_CTX));
6127 SHA1Init(&sha1ctx);
6128
6129 SHA1Update(&sha1ctx, (void *)cval, cval_len);
6130
6131 err = emlxs_BIGNUM_pubkey(port, pubkey, dhval, dhvallen,
6132 key, key_size, dhgp_id, &pubkey_len);
6133
6134 if (err != BIG_OK) {
6135 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
6136 "hash_Cai: SHA1 BIGNUM_pubkey error: 0x%x",
6137 err);
6138
6139 err = BIG_GENERAL_ERR;
6140 return (err);
6141 }
6142 if (pubkey_len == 0) {
6143 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
6144 "hash_Cai: SA1 BUM_pubkey error: key_len=0");
6145
6146 err = BIG_GENERAL_ERR;
6147 return (err);
6148 }
6149 if (ndlp->nlp_DID == FABRIC_DID) {
6150 bcopy((void *)pubkey,
6151 (void *)node_dhc->hrsp_ses_key,
6152 pubkey_len);
6153 node_dhc->hrsp_seskey_len = pubkey_len;
6154
6155 /* store extra copy */
6156 bcopy((void *)pubkey,
6157 (void *)node_dhc->nlp_auth_misc.hrsp_ses_key,
6158 pubkey_len);
6159 node_dhc->nlp_auth_misc.hrsp_seskey_len = pubkey_len;
6160
6161 } else {
6162 bcopy((void *)pubkey,
6163 (void *)node_dhc->nlp_auth_misc.hrsp_ses_key,
6164 pubkey_len);
6165 node_dhc->nlp_auth_misc.hrsp_seskey_len = pubkey_len;
6166 }
6167
6168 SHA1Update(&sha1ctx, (void *)pubkey, pubkey_len);
6169 SHA1Final((void *)sha1_digest, &sha1ctx);
6170 bcopy((void *)&sha1_digest, (void *)Cai, SHA1_LEN);
6171 }
6172 return (err);
6173
6174 } /* emlxs_hash_Cai */
6175
6176
6177 /*
6178 * This routine is to verify the DHCHAP_Reply from initiator by the host
6179 * as the responder.
6180 *
6181 * flag: 1: if host is the responder 0: if host is the initiator
6182 *
6183 * if bi_cval != NULL, this routine is used to calculate the response based
6184 * on the challenge from initiator as part of
6185 * DHCHAP_Reply for bi-dirctional authentication.
6186 *
6187 */
6188 /* ARGSUSED */
6189 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)6190 emlxs_hash_verification(
6191 emlxs_port_t *port,
6192 emlxs_port_dhc_t *port_dhc,
6193 NODELIST *ndlp,
6194 uint32_t tran_id,
6195 uint8_t *dhval,
6196 uint32_t dhval_len,
6197 uint32_t flag, /* always 1 for now */
6198 uint8_t *bi_cval)
6199 { /* always 0 for now */
6200 emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
6201 uint32_t dhgp_id;
6202 uint32_t hash_id;
6203 uint32_t *hash_val = NULL;
6204 uint32_t hash_size;
6205 MD5_CTX mdctx;
6206 SHA1_CTX sha1ctx;
6207 uint8_t sha1_digest[20];
6208 uint8_t md5_digest[16];
6209 uint8_t Cai[20];
6210 /* union challenge_val un_cval; */
6211 uint8_t key[20];
6212 uint8_t cval[20];
6213 uint32_t cval_len;
6214 uint8_t mytran_id = 0x00;
6215 char *remote_key;
6216 BIG_ERR_CODE err = BIG_OK;
6217
6218 tran_id = (AUTH_TRAN_ID_MASK & tran_id);
6219 mytran_id = (uint8_t)(LE_SWAP32(tran_id));
6220
6221 if (ndlp->nlp_DID == FABRIC_DID) {
6222 remote_key = (char *)node_dhc->auth_key.remote_password;
6223 } else {
6224 /*
6225 * in case of end-to-end auth, this remote password should be
6226 * the password associated with the remote entity. (i.e.,)
6227 * for now it is actually local_password.
6228 */
6229 remote_key = (char *)node_dhc->auth_key.remote_password;
6230 }
6231
6232 if (flag == 0) {
6233 dhgp_id = node_dhc->dhgp_id;
6234 hash_id = node_dhc->hash_id;
6235 } else {
6236 dhgp_id = node_dhc->nlp_auth_dhgpid;
6237 hash_id = node_dhc->nlp_auth_hashid;
6238 }
6239
6240 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
6241 "hash_verification: 0x%x 0x%x hash_id=0x%x dhgp_id=0x%x",
6242 ndlp->nlp_DID, mytran_id, hash_id, dhgp_id);
6243
6244 if (dhval_len == 0) {
6245 /* NULL DHCHAP group */
6246 if (hash_id == AUTH_MD5) {
6247 bzero(&mdctx, sizeof (MD5_CTX));
6248 hash_size = MD5_LEN;
6249 MD5Init(&mdctx);
6250
6251 MD5Update(&mdctx, (unsigned char *)&mytran_id, 1);
6252
6253 if (ndlp->nlp_DID == FABRIC_DID) {
6254 MD5Update(&mdctx,
6255 (unsigned char *)remote_key,
6256 node_dhc->auth_key.remote_password_length);
6257 } else {
6258 MD5Update(&mdctx,
6259 (unsigned char *)remote_key,
6260 node_dhc->auth_key.remote_password_length);
6261 }
6262
6263 if (ndlp->nlp_DID == FABRIC_DID) {
6264 MD5Update(&mdctx,
6265 (unsigned char *)&node_dhc->hrsp_cval[0],
6266 MD5_LEN);
6267 } else {
6268 MD5Update(&mdctx,
6269 (unsigned char *)&node_dhc->nlp_auth_misc.hrsp_cval[0],
6270 MD5_LEN);
6271 }
6272
6273 MD5Final((uint8_t *)md5_digest, &mdctx);
6274
6275 hash_val = (uint32_t *)kmem_alloc(hash_size,
6276 KM_NOSLEEP);
6277 if (hash_val == NULL) {
6278 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
6279 "hash_verification: alloc failed");
6280
6281 return (NULL);
6282 } else {
6283 bcopy((void *)md5_digest,
6284 (void *)hash_val, MD5_LEN);
6285 }
6286 }
6287 if (hash_id == AUTH_SHA1) {
6288 bzero(&sha1ctx, sizeof (SHA1_CTX));
6289 hash_size = SHA1_LEN;
6290 SHA1Init(&sha1ctx);
6291 SHA1Update(&sha1ctx, (void *)&mytran_id, 1);
6292
6293 if (ndlp->nlp_DID == FABRIC_DID) {
6294 SHA1Update(&sha1ctx, (void *)remote_key,
6295 node_dhc->auth_key.remote_password_length);
6296 } else {
6297 SHA1Update(&sha1ctx, (void *)remote_key,
6298 node_dhc->auth_key.remote_password_length);
6299 }
6300
6301 if (ndlp->nlp_DID == FABRIC_DID) {
6302 SHA1Update(&sha1ctx,
6303 (void *)&node_dhc->hrsp_cval[0],
6304 SHA1_LEN);
6305 } else {
6306 SHA1Update(&sha1ctx,
6307 (void *)&node_dhc->nlp_auth_misc.hrsp_cval[0],
6308 SHA1_LEN);
6309 }
6310
6311 SHA1Final((void *)sha1_digest, &sha1ctx);
6312 hash_val = (uint32_t *)kmem_zalloc(hash_size,
6313 KM_NOSLEEP);
6314 if (hash_val == NULL) {
6315 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
6316 "hash_verification: alloc failed");
6317
6318 return (NULL);
6319 } else {
6320 bcopy((void *)sha1_digest,
6321 (void *)hash_val, SHA1_LEN);
6322 }
6323 }
6324 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
6325 "hash_verification: hash_val=0x%x",
6326 *(uint32_t *)hash_val);
6327
6328 return ((uint32_t *)hash_val);
6329 } else {
6330
6331 /* DHCHAP group 1,2,3,4 */
6332 /*
6333 * host received (g^x mod p) as dhval host has its own
6334 * private key y as node_dhc->hrsp_priv_key[] host has its
6335 * original challenge c as node_dhc->hrsp_cval[]
6336 *
6337 * H(c || (g^x mod p)^y mod p) = Cai H(Ti || Km || Cai) =
6338 * hash_val returned. Ti : tran_id, Km : shared secret, Cai:
6339 * obtained above.
6340 */
6341 if (hash_id == AUTH_MD5) {
6342 if (ndlp->nlp_DID == FABRIC_DID) {
6343 bcopy((void *)node_dhc->hrsp_priv_key,
6344 (void *)key, MD5_LEN);
6345 } else {
6346 bcopy(
6347 (void *)node_dhc->nlp_auth_misc.hrsp_priv_key,
6348 (void *)key, MD5_LEN);
6349 }
6350 }
6351 if (hash_id == AUTH_SHA1) {
6352 if (ndlp->nlp_DID == FABRIC_DID) {
6353 bcopy((void *)node_dhc->hrsp_priv_key,
6354 (void *)key, SHA1_LEN);
6355 } else {
6356 bcopy(
6357 (void *)node_dhc->nlp_auth_misc.hrsp_priv_key,
6358 (void *)key, SHA1_LEN);
6359 }
6360 }
6361 if (ndlp->nlp_DID == FABRIC_DID) {
6362 bcopy((void *)node_dhc->hrsp_cval,
6363 (void *)cval, node_dhc->hrsp_cval_len);
6364 cval_len = node_dhc->hrsp_cval_len;
6365 } else {
6366 bcopy((void *)node_dhc->nlp_auth_misc.hrsp_cval,
6367 (void *)cval,
6368 node_dhc->nlp_auth_misc.hrsp_cval_len);
6369 cval_len = node_dhc->nlp_auth_misc.hrsp_cval_len;
6370 }
6371
6372 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
6373 "hash_verification: N-Null gp. 0x%x 0x%x",
6374 ndlp->nlp_DID, cval_len);
6375
6376 err = emlxs_hash_Cai(port, port_dhc, ndlp, (void *)Cai,
6377 hash_id, dhgp_id,
6378 tran_id, cval, cval_len,
6379 key, dhval, dhval_len);
6380
6381 if (err != BIG_OK) {
6382 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
6383 "hash_verification: Cai error. ret=0x%x",
6384 err);
6385
6386 return (NULL);
6387 }
6388 if (hash_id == AUTH_MD5) {
6389 bzero(&mdctx, sizeof (MD5_CTX));
6390 hash_size = MD5_LEN;
6391
6392 MD5Init(&mdctx);
6393 MD5Update(&mdctx, (unsigned char *)&mytran_id, 1);
6394
6395 if (ndlp->nlp_DID == FABRIC_DID) {
6396 MD5Update(&mdctx,
6397 (unsigned char *)remote_key,
6398 node_dhc->auth_key.remote_password_length);
6399 } else {
6400 MD5Update(&mdctx,
6401 (unsigned char *)remote_key,
6402 node_dhc->auth_key.remote_password_length);
6403 }
6404
6405 MD5Update(&mdctx, (unsigned char *)Cai, MD5_LEN);
6406 MD5Final((uint8_t *)md5_digest, &mdctx);
6407
6408 hash_val = (uint32_t *)kmem_zalloc(hash_size,
6409 KM_NOSLEEP);
6410 if (hash_val == NULL) {
6411 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
6412 "hash_vf: alloc failed(Non-NULL dh)");
6413
6414 return (NULL);
6415 } else {
6416 bcopy((void *)&md5_digest,
6417 (void *)hash_val, MD5_LEN);
6418 }
6419 }
6420 if (hash_id == AUTH_SHA1) {
6421 bzero(&sha1ctx, sizeof (SHA1_CTX));
6422 hash_size = SHA1_LEN;
6423
6424 SHA1Init(&sha1ctx);
6425 SHA1Update(&sha1ctx, (void *)&mytran_id, 1);
6426
6427 if (ndlp->nlp_DID == FABRIC_DID) {
6428 SHA1Update(&sha1ctx, (void *)remote_key,
6429 node_dhc->auth_key.remote_password_length);
6430 } else {
6431 SHA1Update(&sha1ctx, (void *)remote_key,
6432 node_dhc->auth_key.remote_password_length);
6433 }
6434
6435 SHA1Update(&sha1ctx, (void *)Cai, SHA1_LEN);
6436 SHA1Final((void *)sha1_digest, &sha1ctx);
6437
6438 hash_val = (uint32_t *)kmem_zalloc(hash_size,
6439 KM_NOSLEEP);
6440 if (hash_val == NULL) {
6441 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
6442 "hash_vf: val alloc failed (Non-NULL dh)");
6443
6444 return (NULL);
6445 } else {
6446 bcopy((void *)&sha1_digest,
6447 (void *)hash_val, SHA1_LEN);
6448 }
6449 }
6450 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
6451 "hash_verification: hash_val=0x%x",
6452 *(uint32_t *)hash_val);
6453
6454 return ((uint32_t *)hash_val);
6455 }
6456
6457 } /* emlxs_hash_verification */
6458
6459
6460
6461 /*
6462 * When DHCHAP_Success msg was sent from responder to the initiator,
6463 * with bi-directional authentication requested, the
6464 * DHCHAP_Success contains the response R2 to the challenge C2 received.
6465 *
6466 * DHCHAP response R2: The value of R2 is computed using the hash function
6467 * H() selected by the HashID parameter of the
6468 * DHCHAP_Challenge msg, and the augmented challenge Ca2.
6469 *
6470 * NULL DH group: Ca2 = C2 Non NULL DH group: Ca2 = H(C2 ||
6471 * (g^y mod p)^x mod p)) x is selected by the authentication responder
6472 * which is the node_dhc->hrsp_priv_key[] (g^y mod p) is dhval received
6473 * from authentication initiator.
6474 *
6475 * R2 = H(Ti || Km || Ca2) Ti is the least significant byte of the
6476 * transaction id. Km is the secret associated with the
6477 * authentication responder.
6478 *
6479 * emlxs_hash_get_R2 and emlxs_hash_verification could be mergerd into one
6480 * function later.
6481 *
6482 */
6483 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)6484 emlxs_hash_get_R2(
6485 emlxs_port_t *port,
6486 emlxs_port_dhc_t *port_dhc,
6487 NODELIST *ndlp,
6488 uint32_t tran_id,
6489 uint8_t *dhval,
6490 uint32_t dhval_len,
6491 uint32_t flag, /* flag 1 rsponder or 0 initiator */
6492 uint8_t *bi_cval)
6493 {
6494 emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
6495
6496 uint32_t dhgp_id;
6497 uint32_t hash_id;
6498 uint32_t *hash_val = NULL;
6499 uint32_t hash_size;
6500 MD5_CTX mdctx;
6501 SHA1_CTX sha1ctx;
6502 uint8_t sha1_digest[20];
6503 uint8_t md5_digest[16];
6504 uint8_t Cai[20];
6505 /* union challenge_val un_cval; */
6506 uint8_t key[20];
6507 uint32_t cval_len;
6508 uint8_t mytran_id = 0x00;
6509
6510 char *mykey;
6511 BIG_ERR_CODE err = BIG_OK;
6512
6513 if (ndlp->nlp_DID == FABRIC_DID) {
6514 dhgp_id = node_dhc->nlp_auth_dhgpid;
6515 hash_id = node_dhc->nlp_auth_hashid;
6516 } else {
6517 if (flag == 0) {
6518 dhgp_id = node_dhc->dhgp_id;
6519 hash_id = node_dhc->hash_id;
6520 } else {
6521 dhgp_id = node_dhc->nlp_auth_dhgpid;
6522 hash_id = node_dhc->nlp_auth_hashid;
6523 }
6524 }
6525
6526 tran_id = (AUTH_TRAN_ID_MASK & tran_id);
6527 mytran_id = (uint8_t)(LE_SWAP32(tran_id));
6528
6529 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_detail_msg,
6530 "hash_get_R2:0x%x 0x%x dhgp_id=0x%x mytran_id=0x%x",
6531 ndlp->nlp_DID, hash_id, dhgp_id, mytran_id);
6532
6533 if (ndlp->nlp_DID == FABRIC_DID) {
6534 mykey = (char *)node_dhc->auth_key.local_password;
6535
6536 } else {
6537 /* in case of end-to-end mykey should be remote_password */
6538 mykey = (char *)node_dhc->auth_key.remote_password;
6539 }
6540
6541 if (dhval_len == 0) {
6542 /* NULL DHCHAP group */
6543 if (hash_id == AUTH_MD5) {
6544 bzero(&mdctx, sizeof (MD5_CTX));
6545 hash_size = MD5_LEN;
6546 MD5Init(&mdctx);
6547
6548 MD5Update(&mdctx, (unsigned char *)&mytran_id, 1);
6549
6550 if (ndlp->nlp_DID == FABRIC_DID) {
6551 MD5Update(&mdctx, (unsigned char *)mykey,
6552 node_dhc->auth_key.local_password_length);
6553 } else {
6554 MD5Update(&mdctx, (unsigned char *)mykey,
6555 node_dhc->auth_key.remote_password_length);
6556 }
6557
6558 MD5Update(&mdctx, (unsigned char *)bi_cval, MD5_LEN);
6559
6560 MD5Final((uint8_t *)md5_digest, &mdctx);
6561
6562 hash_val = (uint32_t *)kmem_alloc(hash_size,
6563 KM_NOSLEEP);
6564 if (hash_val == NULL) {
6565 return (NULL);
6566 } else {
6567 bcopy((void *)md5_digest,
6568 (void *)hash_val, MD5_LEN);
6569 }
6570 }
6571 if (hash_id == AUTH_SHA1) {
6572 bzero(&sha1ctx, sizeof (SHA1_CTX));
6573 hash_size = SHA1_LEN;
6574 SHA1Init(&sha1ctx);
6575 SHA1Update(&sha1ctx, (void *)&mytran_id, 1);
6576
6577 if (ndlp->nlp_DID == FABRIC_DID) {
6578 SHA1Update(&sha1ctx, (void *)mykey,
6579 node_dhc->auth_key.local_password_length);
6580 } else {
6581 SHA1Update(&sha1ctx, (void *)mykey,
6582 node_dhc->auth_key.remote_password_length);
6583 }
6584
6585 SHA1Update(&sha1ctx, (void *)bi_cval, SHA1_LEN);
6586 SHA1Final((void *)sha1_digest, &sha1ctx);
6587 hash_val = (uint32_t *)kmem_alloc(hash_size,
6588 KM_NOSLEEP);
6589 if (hash_val == NULL) {
6590 return (NULL);
6591 } else {
6592 bcopy((void *)sha1_digest,
6593 (void *)hash_val, SHA1_LEN);
6594 }
6595 }
6596 } else {
6597 /* NON-NULL DHCHAP */
6598 if (ndlp->nlp_DID == FABRIC_DID) {
6599 if (hash_id == AUTH_MD5) {
6600 bcopy((void *)node_dhc->hrsp_priv_key,
6601 (void *)key, MD5_LEN);
6602 }
6603 if (hash_id == AUTH_SHA1) {
6604 bcopy((void *)node_dhc->hrsp_priv_key,
6605 (void *)key, SHA1_LEN);
6606 }
6607 cval_len = node_dhc->hrsp_cval_len;
6608 } else {
6609 if (hash_id == AUTH_MD5) {
6610 bcopy(
6611 (void *)node_dhc->nlp_auth_misc.hrsp_priv_key,
6612 (void *)key, MD5_LEN);
6613 }
6614 if (hash_id == AUTH_SHA1) {
6615 bcopy(
6616 (void *)node_dhc->nlp_auth_misc.hrsp_priv_key,
6617 (void *)key, SHA1_LEN);
6618 }
6619 cval_len = node_dhc->nlp_auth_misc.hrsp_cval_len;
6620 }
6621
6622 /* use bi_cval here */
6623 /*
6624 * key: x dhval: (g^y mod p) tran_id: Ti bi_cval: C2 hash_id:
6625 * H dhgp_id: p/g
6626 *
6627 * Cai = H (C2 || ((g^y mod p)^x mod p) )
6628 *
6629 * R2 = H (Ti || Km || Cai)
6630 */
6631 err = emlxs_hash_Cai(port, port_dhc, ndlp, (void *)Cai,
6632 hash_id, dhgp_id, tran_id, bi_cval, cval_len,
6633 key, dhval, dhval_len);
6634
6635 if (err != BIG_OK) {
6636 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
6637 "hash_get_R2: hash_Cai error. ret=0x%x",
6638 err);
6639
6640 return (NULL);
6641 }
6642 if (hash_id == AUTH_MD5) {
6643 bzero(&mdctx, sizeof (MD5_CTX));
6644 hash_size = MD5_LEN;
6645
6646 MD5Init(&mdctx);
6647 MD5Update(&mdctx, (unsigned char *) &mytran_id, 1);
6648
6649 /*
6650 * Here we use the same key: mykey, note: this mykey
6651 * should be the key associated with the
6652 * authentication responder i.e. the remote key.
6653 */
6654 if (ndlp->nlp_DID == FABRIC_DID)
6655 MD5Update(&mdctx, (unsigned char *)mykey,
6656 node_dhc->auth_key.local_password_length);
6657 else
6658 MD5Update(&mdctx, (unsigned char *)mykey,
6659 node_dhc->auth_key.remote_password_length);
6660
6661 MD5Update(&mdctx, (unsigned char *)Cai, MD5_LEN);
6662 MD5Final((uint8_t *)md5_digest, &mdctx);
6663
6664 hash_val = (uint32_t *)kmem_alloc(hash_size,
6665 KM_NOSLEEP);
6666 if (hash_val == NULL) {
6667 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
6668 "hash_get_R2: hash_val MD5 alloc failed.");
6669
6670 return (NULL);
6671 } else {
6672 bcopy((void *)md5_digest,
6673 (void *)hash_val, MD5_LEN);
6674 }
6675 }
6676 if (hash_id == AUTH_SHA1) {
6677 bzero(&sha1ctx, sizeof (SHA1_CTX));
6678 hash_size = SHA1_LEN;
6679
6680 SHA1Init(&sha1ctx);
6681 SHA1Update(&sha1ctx, (void *)&mytran_id, 1);
6682
6683 if (ndlp->nlp_DID == FABRIC_DID) {
6684 SHA1Update(&sha1ctx, (void *)mykey,
6685 node_dhc->auth_key.local_password_length);
6686 } else {
6687 SHA1Update(&sha1ctx, (void *)mykey,
6688 node_dhc->auth_key.remote_password_length);
6689 }
6690
6691 SHA1Update(&sha1ctx, (void *)Cai, SHA1_LEN);
6692 SHA1Final((void *)sha1_digest, &sha1ctx);
6693
6694 hash_val = (uint32_t *)kmem_alloc(hash_size,
6695 KM_NOSLEEP);
6696 if (hash_val == NULL) {
6697 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg,
6698 "hash_get_R2: hash_val SHA1 alloc failed.");
6699
6700 return (NULL);
6701 } else {
6702 bcopy((void *)sha1_digest,
6703 (void *)hash_val, SHA1_LEN);
6704 }
6705 }
6706 }
6707
6708 return ((uint32_t *)hash_val);
6709
6710 } /* emlxs_hash_get_R2 */
6711
6712
6713 static void
emlxs_log_auth_event(emlxs_port_t * port,NODELIST * ndlp,char * subclass,char * info)6714 emlxs_log_auth_event(
6715 emlxs_port_t *port,
6716 NODELIST *ndlp,
6717 char *subclass,
6718 char *info)
6719 {
6720 emlxs_hba_t *hba = HBA;
6721 emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
6722 nvlist_t *attr_list = NULL;
6723 dev_info_t *dip = hba->dip;
6724 emlxs_auth_cfg_t *auth_cfg;
6725 char *tmp = "No_more_logging_information_available";
6726 uint8_t lwwn[8];
6727 uint8_t rwwn[8];
6728 char *lwwn_str = NULL;
6729 char *rwwn_str = NULL;
6730 char ext_subclass[128];
6731 char ext_class[32];
6732
6733 auth_cfg = &(node_dhc->auth_cfg);
6734
6735 if (info == NULL) {
6736 info = tmp;
6737 }
6738 bcopy((void *) &auth_cfg->local_entity, (void *)lwwn, 8);
6739 lwwn_str = (char *)kmem_zalloc(32, KM_NOSLEEP);
6740 if (lwwn_str == NULL) {
6741 return;
6742 }
6743 (void) snprintf(lwwn_str, 32, "%02X%02X%02X%02X%02X%02X%02X%02X",
6744 lwwn[0], lwwn[1], lwwn[2], lwwn[3], lwwn[4], lwwn[5], lwwn[6],
6745 lwwn[7]);
6746
6747 bcopy((void *)&auth_cfg->remote_entity, (void *)rwwn, 8);
6748 rwwn_str = (char *)kmem_zalloc(32, KM_NOSLEEP);
6749 if (rwwn_str == NULL) {
6750 kmem_free(lwwn_str, 32);
6751 return;
6752 }
6753
6754 (void) snprintf(rwwn_str, 32, "%02X%02X%02X%02X%02X%02X%02X%02X",
6755 rwwn[0], rwwn[1], rwwn[2], rwwn[3], rwwn[4], rwwn[5], rwwn[6],
6756 rwwn[7]);
6757
6758 (void) snprintf(ext_subclass, sizeof (ext_subclass),
6759 "ESC_%s_%s", DRIVER_NAME, subclass);
6760 (void) snprintf(ext_class, sizeof (ext_class),
6761 "EC_%s", DRIVER_NAME);
6762
6763 if (nvlist_alloc(&attr_list, NV_UNIQUE_NAME_TYPE, KM_NOSLEEP)
6764 == DDI_SUCCESS) {
6765 if ((nvlist_add_uint32(attr_list, "instance",
6766 ddi_get_instance(dip)) == DDI_SUCCESS) &&
6767 (nvlist_add_string(attr_list, "lwwn",
6768 lwwn_str) == DDI_SUCCESS) &&
6769 (nvlist_add_string(attr_list, "rwwn",
6770 rwwn_str) == DDI_SUCCESS) &&
6771 (nvlist_add_string(attr_list, "Info",
6772 info) == DDI_SUCCESS) &&
6773 (nvlist_add_string(attr_list, "Class",
6774 ext_class) == DDI_SUCCESS) &&
6775 (nvlist_add_string(attr_list, "SubClass",
6776 ext_subclass) == DDI_SUCCESS)) {
6777
6778 (void) ddi_log_sysevent(dip,
6779 emlxs_strtoupper(DRIVER_NAME),
6780 ext_class,
6781 ext_subclass,
6782 attr_list,
6783 NULL,
6784 DDI_NOSLEEP);
6785 }
6786 nvlist_free(attr_list);
6787 attr_list = NULL;
6788 }
6789 kmem_free(lwwn_str, 32);
6790 kmem_free(rwwn_str, 32);
6791
6792 return;
6793
6794 } /* emlxs_log_auth_event() */
6795
6796
6797 /* **************************** AUTH DHC INTERFACE ************************* */
6798
6799 extern int
emlxs_dhc_auth_start(emlxs_port_t * port,emlxs_node_t * ndlp,uint8_t * deferred_sbp,uint8_t * deferred_ubp)6800 emlxs_dhc_auth_start(
6801 emlxs_port_t *port,
6802 emlxs_node_t *ndlp,
6803 uint8_t *deferred_sbp,
6804 uint8_t *deferred_ubp)
6805 {
6806 emlxs_hba_t *hba = HBA;
6807 emlxs_config_t *cfg = &CFG;
6808 emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
6809 emlxs_auth_cfg_t *auth_cfg;
6810 emlxs_auth_key_t *auth_key;
6811 uint32_t i;
6812 uint32_t fabric;
6813 uint32_t fabric_switch;
6814
6815 /* The ubp represents an unsolicted PLOGI */
6816 /* The sbp represents a solicted PLOGI */
6817
6818 fabric = ((ndlp->nlp_DID & FABRIC_DID_MASK) == FABRIC_DID_MASK) ? 1 : 0;
6819 fabric_switch = ((ndlp->nlp_DID == FABRIC_DID) ? 1 : 0);
6820
6821 /* Return is authentication is not enabled */
6822 if (cfg[CFG_AUTH_ENABLE].current == 0) {
6823 EMLXS_MSGF(EMLXS_CONTEXT,
6824 &emlxs_fcsp_start_msg,
6825 "Not started. Auth disabled. did=0x%x", ndlp->nlp_DID);
6826
6827 emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_DISABLED, 0, 0);
6828
6829 return (1);
6830 }
6831 if (port->vpi != 0 && cfg[CFG_AUTH_NPIV].current == 0) {
6832 EMLXS_MSGF(EMLXS_CONTEXT,
6833 &emlxs_fcsp_start_msg,
6834 "Not started. NPIV auth disabled. did=0x%x", ndlp->nlp_DID);
6835
6836 emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_DISABLED, 0, 0);
6837
6838 return (1);
6839 }
6840 if (!fabric_switch && fabric) {
6841 EMLXS_MSGF(EMLXS_CONTEXT,
6842 &emlxs_fcsp_start_msg,
6843 "Not started. FS auth disabled. did=0x%x", ndlp->nlp_DID);
6844
6845 emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_DISABLED, 0, 0);
6846
6847 return (1);
6848 }
6849 /* Return if fcsp support to this node is not enabled */
6850 if (!fabric_switch && cfg[CFG_AUTH_E2E].current == 0) {
6851 EMLXS_MSGF(EMLXS_CONTEXT,
6852 &emlxs_fcsp_start_msg,
6853 "Not started. E2E auth disabled. did=0x%x", ndlp->nlp_DID);
6854
6855 emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_DISABLED, 0, 0);
6856
6857 return (1);
6858 }
6859 if ((deferred_sbp && node_dhc->deferred_sbp) ||
6860 (deferred_ubp && node_dhc->deferred_ubp)) {
6861 /* Clear previous authentication */
6862 emlxs_dhc_auth_stop(port, ndlp);
6863 }
6864 mutex_enter(&hba->auth_lock);
6865
6866 /* Intialize node */
6867 node_dhc->parent_auth_cfg = NULL;
6868 node_dhc->parent_auth_key = NULL;
6869
6870 /* Acquire auth configuration */
6871 if (fabric_switch) {
6872 auth_cfg = emlxs_auth_cfg_find(port,
6873 (uint8_t *)emlxs_fabric_wwn);
6874 auth_key = emlxs_auth_key_find(port,
6875 (uint8_t *)emlxs_fabric_wwn);
6876 } else {
6877 auth_cfg = emlxs_auth_cfg_find(port,
6878 (uint8_t *)&ndlp->nlp_portname);
6879 auth_key = emlxs_auth_key_find(port,
6880 (uint8_t *)&ndlp->nlp_portname);
6881 }
6882
6883 if (!auth_cfg) {
6884 mutex_exit(&hba->auth_lock);
6885
6886 EMLXS_MSGF(EMLXS_CONTEXT,
6887 &emlxs_fcsp_start_msg,
6888 "Not started. No auth cfg entry found. did=0x%x",
6889 ndlp->nlp_DID);
6890
6891 emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_DISABLED, 0, 0);
6892
6893 return (1);
6894 }
6895 if (fabric_switch) {
6896 auth_cfg->node = NULL;
6897 } else {
6898 node_dhc->parent_auth_cfg = auth_cfg;
6899 auth_cfg->node = ndlp;
6900 }
6901
6902 if (!auth_key) {
6903 mutex_exit(&hba->auth_lock);
6904
6905 EMLXS_MSGF(EMLXS_CONTEXT,
6906 &emlxs_fcsp_start_msg,
6907 "Not started. No auth key entry found. did=0x%x",
6908 ndlp->nlp_DID);
6909
6910 emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_DISABLED, 0, 0);
6911
6912 return (1);
6913 }
6914 if (fabric_switch) {
6915 auth_key->node = NULL;
6916 } else {
6917 node_dhc->parent_auth_key = auth_key;
6918 auth_key->node = ndlp;
6919 }
6920
6921 /* Remote port does not support fcsp */
6922 if (ndlp->sparm.cmn.fcsp_support == 0) {
6923 switch (auth_cfg->authentication_mode) {
6924 case AUTH_MODE_PASSIVE:
6925 mutex_exit(&hba->auth_lock);
6926
6927 EMLXS_MSGF(EMLXS_CONTEXT,
6928 &emlxs_fcsp_start_msg,
6929 "Not started. Auth unsupported. did=0x%x",
6930 ndlp->nlp_DID);
6931
6932 emlxs_dhc_state(port, ndlp,
6933 NODE_STATE_AUTH_DISABLED, 0, 0);
6934 return (1);
6935
6936 case AUTH_MODE_ACTIVE:
6937 mutex_exit(&hba->auth_lock);
6938
6939 EMLXS_MSGF(EMLXS_CONTEXT,
6940 &emlxs_fcsp_start_msg,
6941 "Failed. Auth unsupported. did=0x%x",
6942 ndlp->nlp_DID);
6943
6944 /*
6945 * Save packet for deferred completion until
6946 * authentication is complete
6947 */
6948 ndlp->node_dhc.deferred_sbp = deferred_sbp;
6949 ndlp->node_dhc.deferred_ubp = deferred_ubp;
6950
6951 goto failed;
6952
6953 case AUTH_MODE_DISABLED:
6954 default:
6955 mutex_exit(&hba->auth_lock);
6956
6957 EMLXS_MSGF(EMLXS_CONTEXT,
6958 &emlxs_fcsp_start_msg,
6959 "Not started. Auth mode=disabled. did=0x%x",
6960 ndlp->nlp_DID);
6961
6962 emlxs_dhc_state(port, ndlp,
6963 NODE_STATE_AUTH_DISABLED, 0, 0);
6964 return (1);
6965 }
6966 } else { /* Remote port supports fcsp */
6967 switch (auth_cfg->authentication_mode) {
6968 case AUTH_MODE_PASSIVE:
6969 case AUTH_MODE_ACTIVE:
6970 /* start auth */
6971 break;
6972
6973 case AUTH_MODE_DISABLED:
6974 default:
6975 mutex_exit(&hba->auth_lock);
6976
6977 EMLXS_MSGF(EMLXS_CONTEXT,
6978 &emlxs_fcsp_start_msg,
6979 "Failed. Auth mode=disabled. did=0x%x",
6980 ndlp->nlp_DID);
6981
6982 /*
6983 * Save packet for deferred completion until
6984 * authentication is complete
6985 */
6986 ndlp->node_dhc.deferred_sbp = deferred_sbp;
6987 ndlp->node_dhc.deferred_ubp = deferred_ubp;
6988
6989 goto failed;
6990 }
6991 }
6992
6993 /* We have a GO for authentication */
6994
6995 /*
6996 * Save pointers for deferred completion until authentication is
6997 * complete
6998 */
6999 node_dhc->deferred_sbp = deferred_sbp;
7000 node_dhc->deferred_ubp = deferred_ubp;
7001
7002 bzero(&node_dhc->auth_cfg, sizeof (node_dhc->auth_cfg));
7003 bzero(&node_dhc->auth_key, sizeof (node_dhc->auth_key));
7004
7005 /* Program node's auth cfg */
7006 bcopy((uint8_t *)&port->wwpn,
7007 (uint8_t *)&node_dhc->auth_cfg.local_entity, 8);
7008 bcopy((uint8_t *)&ndlp->nlp_portname,
7009 (uint8_t *)&node_dhc->auth_cfg.remote_entity, 8);
7010
7011 node_dhc->auth_cfg.authentication_timeout =
7012 auth_cfg->authentication_timeout;
7013 node_dhc->auth_cfg.authentication_mode =
7014 auth_cfg->authentication_mode;
7015
7016 /*
7017 * If remote password type is "ignore", then only unidirectional auth
7018 * is allowed
7019 */
7020 if (auth_key->remote_password_type == 3) {
7021 node_dhc->auth_cfg.bidirectional = 0;
7022 } else {
7023 node_dhc->auth_cfg.bidirectional = auth_cfg->bidirectional;
7024 }
7025
7026 node_dhc->auth_cfg.reauthenticate_time_interval =
7027 auth_cfg->reauthenticate_time_interval;
7028
7029 for (i = 0; i < 4; i++) {
7030 switch (auth_cfg->authentication_type_priority[i]) {
7031 case ELX_DHCHAP:
7032 node_dhc->auth_cfg.authentication_type_priority[i] =
7033 AUTH_DHCHAP;
7034 break;
7035
7036 case ELX_FCAP:
7037 node_dhc->auth_cfg.authentication_type_priority[i] =
7038 AUTH_FCAP;
7039 break;
7040
7041 case ELX_FCPAP:
7042 node_dhc->auth_cfg.authentication_type_priority[i] =
7043 AUTH_FCPAP;
7044 break;
7045
7046 case ELX_KERBEROS:
7047 node_dhc->auth_cfg.authentication_type_priority[i] =
7048 AUTH_KERBEROS;
7049 break;
7050
7051 default:
7052 node_dhc->auth_cfg.authentication_type_priority[i] =
7053 0;
7054 break;
7055 }
7056
7057 switch (auth_cfg->hash_priority[i]) {
7058 case ELX_SHA1:
7059 node_dhc->auth_cfg.hash_priority[i] = AUTH_SHA1;
7060 break;
7061
7062 case ELX_MD5:
7063 node_dhc->auth_cfg.hash_priority[i] = AUTH_MD5;
7064 break;
7065
7066 default:
7067 node_dhc->auth_cfg.hash_priority[i] = 0;
7068 break;
7069 }
7070 }
7071
7072 for (i = 0; i < 8; i++) {
7073 switch (auth_cfg->dh_group_priority[i]) {
7074 case ELX_GROUP_NULL:
7075 node_dhc->auth_cfg.dh_group_priority[i] = GROUP_NULL;
7076 break;
7077
7078 case ELX_GROUP_1024:
7079 node_dhc->auth_cfg.dh_group_priority[i] = GROUP_1024;
7080 break;
7081
7082 case ELX_GROUP_1280:
7083 node_dhc->auth_cfg.dh_group_priority[i] = GROUP_1280;
7084 break;
7085
7086 case ELX_GROUP_1536:
7087 node_dhc->auth_cfg.dh_group_priority[i] = GROUP_1536;
7088 break;
7089
7090 case ELX_GROUP_2048:
7091 node_dhc->auth_cfg.dh_group_priority[i] = GROUP_2048;
7092 break;
7093
7094 default:
7095 node_dhc->auth_cfg.dh_group_priority[i] = 0xF;
7096 break;
7097 }
7098 }
7099
7100 /* Program the node's key */
7101 if (auth_key) {
7102 bcopy((uint8_t *)auth_key,
7103 (uint8_t *)&node_dhc->auth_key,
7104 sizeof (emlxs_auth_key_t));
7105 node_dhc->auth_key.next = NULL;
7106 node_dhc->auth_key.prev = NULL;
7107
7108 bcopy((uint8_t *)&port->wwpn,
7109 (uint8_t *)&node_dhc->auth_key.local_entity, 8);
7110 bcopy((uint8_t *)&ndlp->nlp_portname,
7111 (uint8_t *)&node_dhc->auth_key.remote_entity,
7112 8);
7113 }
7114 mutex_exit(&hba->auth_lock);
7115
7116 node_dhc->nlp_auth_limit = 2;
7117 node_dhc->nlp_fb_vendor = 1;
7118
7119 node_dhc->nlp_authrsp_tmocnt = 0;
7120 node_dhc->nlp_authrsp_tmo = 0;
7121
7122 if (deferred_ubp) {
7123 /* Acknowledge the unsolicited PLOGI */
7124 /* This should trigger the other port to start authentication */
7125 if (emlxs_ub_send_login_acc(port,
7126 (fc_unsol_buf_t *)deferred_ubp) != FC_SUCCESS) {
7127 EMLXS_MSGF(EMLXS_CONTEXT,
7128 &emlxs_fcsp_start_msg,
7129 "Not started. Unable to send PLOGI ACC. did=0x%x",
7130 ndlp->nlp_DID);
7131
7132 goto failed;
7133 }
7134 /* Start the auth rsp timer */
7135 node_dhc->nlp_authrsp_tmo = DRV_TIME +
7136 node_dhc->auth_cfg.authentication_timeout;
7137
7138 EMLXS_MSGF(EMLXS_CONTEXT,
7139 &emlxs_fcsp_start_msg,
7140 "Authrsp timer activated. did=0x%x",
7141 ndlp->nlp_DID);
7142
7143 /* The next state should be emlxs_rcv_auth_msg_unmapped_node */
7144 emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_SUCCESS, 0, 0);
7145 } else {
7146 node_dhc->nlp_auth_flag = 1; /* host is the initiator */
7147
7148 EMLXS_MSGF(EMLXS_CONTEXT,
7149 &emlxs_fcsp_start_msg,
7150 "Auth initiated. did=0x%x limit=%d sbp=%p",
7151 ndlp->nlp_DID, node_dhc->nlp_auth_limit, deferred_sbp);
7152
7153 if (emlxs_issue_auth_negotiate(port, ndlp, 0)) {
7154 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_start_msg,
7155 "Failed. Auth initiation failed. did=0x%x",
7156 ndlp->nlp_DID);
7157
7158 goto failed;
7159 }
7160 }
7161
7162 return (0);
7163
7164 failed:
7165
7166 emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_FAILED, 0, 0);
7167
7168 /* Complete authentication with failed status */
7169 emlxs_dhc_auth_complete(port, ndlp, 1);
7170
7171 return (0);
7172
7173 } /* emlxs_dhc_auth_start() */
7174
7175
7176
7177 /* This is called to indicate the driver has lost connection with this node */
7178 extern void
emlxs_dhc_auth_stop(emlxs_port_t * port,emlxs_node_t * ndlp)7179 emlxs_dhc_auth_stop(
7180 emlxs_port_t *port,
7181 emlxs_node_t *ndlp)
7182 {
7183 emlxs_port_dhc_t *port_dhc = &port->port_dhc;
7184 emlxs_node_dhc_t *node_dhc;
7185 uint32_t i;
7186
7187 if (port_dhc->state == ELX_FABRIC_STATE_UNKNOWN) {
7188 /* Nothing to stop */
7189 return;
7190 }
7191 if (ndlp) {
7192 node_dhc = &ndlp->node_dhc;
7193
7194 if (node_dhc->state == NODE_STATE_UNKNOWN) {
7195 /* Nothing to stop */
7196 return;
7197 }
7198 if (ndlp->nlp_DID != FABRIC_DID) {
7199 emlxs_dhc_state(port, ndlp, NODE_STATE_UNKNOWN, 0, 0);
7200 }
7201 emlxs_dhc_auth_complete(port, ndlp, 2);
7202 } else { /* Lost connection to all nodes for this port */
7203 rw_enter(&port->node_rwlock, RW_READER);
7204 for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
7205 ndlp = port->node_table[i];
7206
7207 if (!ndlp) {
7208 continue;
7209 }
7210 node_dhc = &ndlp->node_dhc;
7211
7212 if (node_dhc->state == NODE_STATE_UNKNOWN) {
7213 continue;
7214 }
7215 if (ndlp->nlp_DID != FABRIC_DID) {
7216 emlxs_dhc_state(port, ndlp,
7217 NODE_STATE_UNKNOWN, 0, 0);
7218 }
7219 emlxs_dhc_auth_complete(port, ndlp, 2);
7220 }
7221 rw_exit(&port->node_rwlock);
7222 }
7223
7224 return;
7225
7226 } /* emlxs_dhc_auth_stop */
7227
7228
7229 /* state = 0 - Successful completion. Continue connection to node */
7230 /* state = 1 - Failed completion. Do not continue with connection to node */
7231 /* state = 2 - Stopped completion. Do not continue with connection to node */
7232
7233 static void
emlxs_dhc_auth_complete(emlxs_port_t * port,emlxs_node_t * ndlp,uint32_t status)7234 emlxs_dhc_auth_complete(
7235 emlxs_port_t *port,
7236 emlxs_node_t *ndlp,
7237 uint32_t status)
7238 {
7239 emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
7240 uint32_t fabric;
7241 uint32_t fabric_switch;
7242
7243 fabric = ((ndlp->nlp_DID & FABRIC_DID_MASK) == FABRIC_DID_MASK) ? 1 : 0;
7244 fabric_switch = ((ndlp->nlp_DID == FABRIC_DID) ? 1 : 0);
7245
7246 EMLXS_MSGF(EMLXS_CONTEXT,
7247 &emlxs_fcsp_complete_msg,
7248 "did=0x%x status=%d sbp=%p ubp=%p",
7249 ndlp->nlp_DID, status, node_dhc->deferred_sbp,
7250 node_dhc->deferred_ubp);
7251
7252 if (status == 1) {
7253 if (fabric_switch) {
7254 /* Virtual link down */
7255 (void) emlxs_port_offline(port, 0xfeffffff);
7256 } else if (!fabric) {
7257 /* Port offline */
7258 (void) emlxs_port_offline(port, ndlp->nlp_DID);
7259 }
7260 }
7261 /* Send a LOGO if authentication was not successful */
7262 if (status == 1) {
7263 EMLXS_MSGF(EMLXS_CONTEXT,
7264 &emlxs_fcsp_complete_msg,
7265 "Sending LOGO to did=0x%x...",
7266 ndlp->nlp_DID);
7267 emlxs_send_logo(port, ndlp->nlp_DID);
7268 }
7269
7270 /* Process deferred cmpl now */
7271 emlxs_mb_deferred_cmpl(port, status,
7272 (emlxs_buf_t *)node_dhc->deferred_sbp,
7273 (fc_unsol_buf_t *)node_dhc->deferred_ubp, 0);
7274
7275 node_dhc->deferred_sbp = 0;
7276 node_dhc->deferred_ubp = 0;
7277
7278 return;
7279
7280 } /* emlxs_dhc_auth_complete */
7281
7282
7283 extern void
emlxs_dhc_attach(emlxs_hba_t * hba)7284 emlxs_dhc_attach(emlxs_hba_t *hba)
7285 {
7286 mutex_init(&hba->auth_lock, NULL, MUTEX_DRIVER, NULL);
7287
7288 mutex_init(&hba->dhc_lock, NULL, MUTEX_DRIVER, NULL);
7289
7290 emlxs_auth_cfg_init(hba);
7291
7292 emlxs_auth_key_init(hba);
7293
7294 hba->rdn_flag = 1;
7295
7296 return;
7297
7298 } /* emlxs_dhc_attach() */
7299
7300
7301 extern void
emlxs_dhc_detach(emlxs_hba_t * hba)7302 emlxs_dhc_detach(emlxs_hba_t *hba)
7303 {
7304 emlxs_auth_cfg_fini(hba);
7305
7306 emlxs_auth_key_fini(hba);
7307
7308 mutex_destroy(&hba->dhc_lock);
7309 mutex_destroy(&hba->auth_lock);
7310
7311 return;
7312
7313 } /* emlxs_dhc_detach() */
7314
7315
7316 extern void
emlxs_dhc_init_sp(emlxs_port_t * port,uint32_t did,SERV_PARM * sp,char ** msg)7317 emlxs_dhc_init_sp(emlxs_port_t *port, uint32_t did, SERV_PARM *sp, char **msg)
7318 {
7319 emlxs_hba_t *hba = HBA;
7320 emlxs_config_t *cfg = &CFG;
7321 uint32_t fabric;
7322 uint32_t fabric_switch;
7323 emlxs_auth_cfg_t *auth_cfg = NULL;
7324 emlxs_auth_key_t *auth_key = NULL;
7325
7326 fabric = ((did & FABRIC_DID_MASK) == FABRIC_DID_MASK) ? 1 : 0;
7327 fabric_switch = ((did == FABRIC_DID) ? 1 : 0);
7328
7329 /* Return is authentication is not enabled */
7330 if (cfg[CFG_AUTH_ENABLE].current == 0) {
7331 sp->cmn.fcsp_support = 0;
7332 bcopy("fcsp:Disabled (0)", (void *) &msg[0],
7333 sizeof ("fcsp:Disabled (0)"));
7334 return;
7335 }
7336
7337 if (port->vpi != 0 && cfg[CFG_AUTH_NPIV].current == 0) {
7338 sp->cmn.fcsp_support = 0;
7339 bcopy("fcsp:Disabled (npiv)", (void *) &msg[0],
7340 sizeof ("fcsp:Disabled (npiv)"));
7341 return;
7342 }
7343 if (!fabric_switch && fabric) {
7344 sp->cmn.fcsp_support = 0;
7345 bcopy("fcsp:Disabled (fs)", (void *) &msg[0],
7346 sizeof ("fcsp:Disabled (fs)"));
7347 return;
7348 }
7349 /* Return if fcsp support to this node is not enabled */
7350 if (!fabric_switch && cfg[CFG_AUTH_E2E].current == 0) {
7351 sp->cmn.fcsp_support = 0;
7352 bcopy("fcsp:Disabled (e2e)", (void *) &msg[0],
7353 sizeof ("fcsp:Disabled (e2e)"));
7354 return;
7355 }
7356
7357 mutex_enter(&hba->auth_lock);
7358 if (fabric_switch) {
7359 auth_cfg = emlxs_auth_cfg_find(port,
7360 (uint8_t *)emlxs_fabric_wwn);
7361 auth_key = emlxs_auth_key_find(port,
7362 (uint8_t *)emlxs_fabric_wwn);
7363 if ((!auth_cfg) || (!auth_key)) {
7364 sp->cmn.fcsp_support = 0;
7365 bcopy("fcsp:Disabled (1)", (void *) &msg[0],
7366 sizeof ("fcsp:Disabled (1)"));
7367 mutex_exit(&hba->auth_lock);
7368 return;
7369 }
7370 }
7371 mutex_exit(&hba->auth_lock);
7372
7373 sp->cmn.fcsp_support = 1;
7374
7375 return;
7376
7377 } /* emlxs_dhc_init_sp() */
7378
7379
7380 extern uint32_t
emlxs_dhc_verify_login(emlxs_port_t * port,uint32_t sid,SERV_PARM * sp)7381 emlxs_dhc_verify_login(emlxs_port_t *port, uint32_t sid, SERV_PARM *sp)
7382 {
7383 emlxs_hba_t *hba = HBA;
7384 emlxs_config_t *cfg = &CFG;
7385 emlxs_auth_cfg_t *auth_cfg;
7386 emlxs_auth_key_t *auth_key;
7387 uint32_t fabric;
7388 uint32_t fabric_switch;
7389
7390 fabric = ((sid & FABRIC_DID_MASK) == FABRIC_DID_MASK) ? 1 : 0;
7391 fabric_switch = ((sid == FABRIC_DID) ? 1 : 0);
7392
7393 if (port->port_dhc.state == ELX_FABRIC_AUTH_FAILED) {
7394 /* Reject login */
7395 return (1);
7396 }
7397 /* Remote host supports FCSP */
7398 if (sp->cmn.fcsp_support) {
7399 /* Continue login */
7400 return (0);
7401 }
7402 /* Auth disabled in host */
7403 if (cfg[CFG_AUTH_ENABLE].current == 0) {
7404 /* Continue login */
7405 return (0);
7406 }
7407 /* Auth disabled for npiv */
7408 if (port->vpi != 0 && cfg[CFG_AUTH_NPIV].current == 0) {
7409 /* Continue login */
7410 return (0);
7411 }
7412 if (!fabric_switch && fabric) {
7413 /* Continue login */
7414 return (0);
7415 }
7416 /* Auth disabled for p2p */
7417 if (!fabric_switch && cfg[CFG_AUTH_E2E].current == 0) {
7418 /* Continue login */
7419 return (0);
7420 }
7421
7422 /* Remote port does NOT support FCSP */
7423 /* Host has FCSP enabled */
7424 /* Now check to make sure auth mode for this port is also enabled */
7425
7426 mutex_enter(&hba->auth_lock);
7427
7428 /* Acquire auth configuration */
7429 if (fabric_switch) {
7430 auth_cfg = emlxs_auth_cfg_find(port,
7431 (uint8_t *)emlxs_fabric_wwn);
7432 auth_key = emlxs_auth_key_find(port,
7433 (uint8_t *)emlxs_fabric_wwn);
7434 } else {
7435 auth_cfg = emlxs_auth_cfg_find(port,
7436 (uint8_t *)&sp->portName);
7437 auth_key = emlxs_auth_key_find(port,
7438 (uint8_t *)&sp->portName);
7439 }
7440
7441 if (auth_key && auth_cfg &&
7442 (auth_cfg->authentication_mode == AUTH_MODE_ACTIVE)) {
7443 mutex_exit(&hba->auth_lock);
7444
7445 /* Reject login */
7446 return (1);
7447 }
7448 mutex_exit(&hba->auth_lock);
7449
7450 return (0);
7451
7452 } /* emlxs_dhc_verify_login() */
7453
7454
7455 /*
7456 * ! emlxs_dhc_reauth_timeout
7457 *
7458 * \pre \post \param phba \param arg1: \param arg2: ndlp to which the host
7459 * is to be authenticated. \return void
7460 *
7461 * \b Description:
7462 *
7463 * Timeout handler for reauthentication heartbeat.
7464 *
7465 * The reauthentication heart beat will be triggered 1 min by default after
7466 * the first authentication success. reauth_intval is
7467 * configurable. if reauth_intval is set to zero, it means no reauth heart
7468 * beat anymore.
7469 *
7470 * reauth heart beat will be triggered by IOCTL call from user space. Reauth
7471 * heart beat will go through the authentication process
7472 * all over again without causing IO traffic disruption. Initially it should
7473 * be triggered after authentication success.
7474 * Subsequently disable/enable reauth heart beat will be performed by
7475 * HBAnyware or other utility.
7476 *
7477 */
7478 /* ARGSUSED */
7479 extern void
emlxs_dhc_reauth_timeout(emlxs_port_t * port,void * arg1,void * arg2)7480 emlxs_dhc_reauth_timeout(
7481 emlxs_port_t *port,
7482 void *arg1,
7483 void *arg2)
7484 {
7485 emlxs_port_dhc_t *port_dhc = &port->port_dhc;
7486 NODELIST *ndlp = (NODELIST *) arg2;
7487 emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
7488
7489 if (node_dhc->auth_cfg.reauthenticate_time_interval == 0) {
7490 EMLXS_MSGF(EMLXS_CONTEXT,
7491 &emlxs_fcsp_debug_msg,
7492 "Reauth timeout. Reauth no longer enabled. 0x%x %x",
7493 ndlp->nlp_DID, node_dhc->state);
7494
7495 emlxs_dhc_set_reauth_time(port, ndlp, DISABLE);
7496
7497 return;
7498 }
7499 /* This should not happen!! */
7500 if (port_dhc->state == ELX_FABRIC_IN_AUTH) {
7501 EMLXS_MSGF(EMLXS_CONTEXT,
7502 &emlxs_fcsp_error_msg,
7503 "Reauth timeout. Fabric in auth. Quiting. 0x%x %x",
7504 ndlp->nlp_DID, node_dhc->state);
7505
7506 emlxs_dhc_set_reauth_time(port, ndlp, DISABLE);
7507
7508 return;
7509 }
7510 if (node_dhc->state != NODE_STATE_AUTH_SUCCESS) {
7511 EMLXS_MSGF(EMLXS_CONTEXT,
7512 &emlxs_fcsp_debug_msg,
7513 "Reauth timeout. Auth not done. Restarting. 0x%x %x",
7514 ndlp->nlp_DID, node_dhc->state);
7515
7516 goto restart;
7517 }
7518 /*
7519 * This might happen, the ndlp is doing reauthencation. meaning ndlp
7520 * is being re-authenticated to the host. Thus not necessary to have
7521 * host re-authenticated to the ndlp at this point because ndlp might
7522 * support bi-directional auth. we can just simply donothing and
7523 * restart the timer.
7524 */
7525 if (port_dhc->state == ELX_FABRIC_IN_REAUTH) {
7526 EMLXS_MSGF(EMLXS_CONTEXT,
7527 &emlxs_fcsp_debug_msg,
7528 "Reauth timeout. Fabric in reauth. Restarting. 0x%x %x",
7529 ndlp->nlp_DID, node_dhc->state);
7530
7531 goto restart;
7532 }
7533 /*
7534 * node's reauth heart beat is running already, cancel it first and
7535 * then restart
7536 */
7537 if (node_dhc->nlp_reauth_status == NLP_HOST_REAUTH_IN_PROGRESS) {
7538 EMLXS_MSGF(EMLXS_CONTEXT,
7539 &emlxs_fcsp_debug_msg,
7540 "Reauth timeout. Fabric in reauth. Restarting. 0x%x %x",
7541 ndlp->nlp_DID, node_dhc->state);
7542
7543 goto restart;
7544 }
7545 EMLXS_MSGF(EMLXS_CONTEXT,
7546 &emlxs_fcsp_debug_msg,
7547 "Reauth timeout. Auth initiated. did=0x%x",
7548 ndlp->nlp_DID);
7549
7550 emlxs_dhc_set_reauth_time(port, ndlp, ENABLE);
7551 node_dhc->nlp_reauth_status = NLP_HOST_REAUTH_IN_PROGRESS;
7552
7553 /* Attempt to restart authentication */
7554 if (emlxs_dhc_auth_start(port, ndlp, NULL, NULL) != 0) {
7555 EMLXS_MSGF(EMLXS_CONTEXT,
7556 &emlxs_fcsp_debug_msg,
7557 "Reauth timeout. Auth initiation failed. 0x%x %x",
7558 ndlp->nlp_DID, node_dhc->state);
7559
7560 return;
7561 }
7562 return;
7563
7564 restart:
7565
7566 emlxs_dhc_set_reauth_time(port, ndlp, ENABLE);
7567
7568 return;
7569
7570 } /* emlxs_dhc_reauth_timeout */
7571
7572
7573 static void
emlxs_dhc_set_reauth_time(emlxs_port_t * port,emlxs_node_t * ndlp,uint32_t status)7574 emlxs_dhc_set_reauth_time(
7575 emlxs_port_t *port,
7576 emlxs_node_t *ndlp,
7577 uint32_t status)
7578 {
7579 emlxs_port_dhc_t *port_dhc = &port->port_dhc;
7580 emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
7581 uint32_t drv_time;
7582 uint32_t timeout;
7583 uint32_t reauth_tmo;
7584 time_t last_auth_time;
7585
7586 node_dhc->flag &= ~NLP_SET_REAUTH_TIME;
7587
7588 if ((status == ENABLE) &&
7589 node_dhc->auth_cfg.reauthenticate_time_interval) {
7590
7591 timeout =
7592 (60 * node_dhc->auth_cfg.reauthenticate_time_interval);
7593 drv_time = DRV_TIME;
7594
7595 /* Get last successful auth time */
7596 if (ndlp->nlp_DID == FABRIC_DID) {
7597 last_auth_time = port_dhc->auth_time;
7598 } else if (node_dhc->parent_auth_cfg) {
7599 last_auth_time = node_dhc->parent_auth_cfg->auth_time;
7600 } else {
7601 last_auth_time = 0;
7602 }
7603
7604 if (last_auth_time) {
7605 reauth_tmo = last_auth_time + timeout;
7606
7607 /* Validate reauth_tmo */
7608 if ((reauth_tmo < drv_time) ||
7609 (reauth_tmo > drv_time + timeout)) {
7610 reauth_tmo = drv_time + timeout;
7611 }
7612 } else {
7613 reauth_tmo = drv_time + timeout;
7614 }
7615
7616 node_dhc->nlp_reauth_tmo = reauth_tmo;
7617 node_dhc->nlp_reauth_status = NLP_HOST_REAUTH_ENABLED;
7618
7619 EMLXS_MSGF(EMLXS_CONTEXT,
7620 &emlxs_fcsp_debug_msg,
7621 "Reauth enabled. did=0x%x state=%x tmo=%d,%d",
7622 ndlp->nlp_DID, node_dhc->state,
7623 node_dhc->auth_cfg.reauthenticate_time_interval,
7624 (reauth_tmo - drv_time));
7625
7626 } else {
7627 node_dhc->nlp_reauth_tmo = 0;
7628 node_dhc->nlp_reauth_status = NLP_HOST_REAUTH_DISABLED;
7629
7630 EMLXS_MSGF(EMLXS_CONTEXT,
7631 &emlxs_fcsp_debug_msg,
7632 "Reauth disabled. did=0x%x state=%x",
7633 ndlp->nlp_DID, node_dhc->state);
7634 }
7635
7636 return;
7637
7638 } /* emlxs_dhc_set_reauth_time */
7639
7640
7641 /* ARGSUSED */
7642 extern void
emlxs_dhc_authrsp_timeout(emlxs_port_t * port,void * arg1,void * arg2)7643 emlxs_dhc_authrsp_timeout(
7644 emlxs_port_t *port,
7645 void *arg1,
7646 void *arg2)
7647 {
7648 NODELIST *ndlp = (NODELIST *)arg1;
7649 emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc;
7650 uint8_t ReasonCode;
7651 uint8_t ReasonCodeExplanation;
7652
7653 node_dhc->nlp_authrsp_tmo = 0;
7654 node_dhc->nlp_authrsp_tmocnt++;
7655
7656 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_debug_msg,
7657 "Authrsp timeout. did=0x%x count=%d",
7658 ndlp->nlp_DID, node_dhc->nlp_authrsp_tmocnt);
7659
7660 /*
7661 * According to the FC-SP spec v1.8 pp76.
7662 *
7663 * When the AUTH_TMO error is detected, the entity may: 1. Act as if the
7664 * authentication transaction has failed and terminate the
7665 * communication; or 2. Restart a new authentication transaction, by
7666 * sending an AUTH_Reject msg with Reason Code `Logical Error' and
7667 * Reason Code Explanation 'Restart Authentication Protocol', The
7668 * action performed by the entity receiving such a AUTH_Reject should
7669 * restart the authentication Transaction by sending a new
7670 * AUTH_Negotiate. We plan to use 2 as the action for now.
7671 *
7672 */
7673
7674 if (node_dhc->nlp_authrsp_tmocnt > 3) {
7675 /* Generate a remove event for the nodelist entry */
7676 (void) emlxs_dhchap_state_machine(port, NULL, NULL,
7677 NULL, ndlp, NODE_EVENT_DEVICE_RM);
7678
7679 ReasonCode = AUTHRJT_FAILURE;
7680 ReasonCodeExplanation = AUTHEXP_AUTH_FAILED;
7681 } else {
7682 /* Generate a recovery event for the nodelist entry */
7683 (void) emlxs_dhchap_state_machine(port, NULL, NULL,
7684 NULL, ndlp, NODE_EVENT_DEVICE_RECOVERY);
7685
7686 ReasonCode = AUTHRJT_LOGIC_ERR;
7687 ReasonCodeExplanation = AUTHEXP_RESTART_AUTH;
7688 }
7689
7690 emlxs_dhc_state(port, ndlp, NODE_STATE_AUTH_FAILED, ReasonCode,
7691 ReasonCodeExplanation);
7692 (void) emlxs_issue_auth_reject(port, ndlp, 0, 0, ReasonCode,
7693 ReasonCodeExplanation);
7694 emlxs_dhc_auth_complete(port, ndlp, 1);
7695
7696 /*
7697 * It is expected the other party should restart the authentication
7698 * transaction
7699 */
7700
7701 return;
7702
7703 } /* emlxs_dhc_authrsp_timeout() */
7704
7705
7706 /* **************************** AUTH CFG MANAGEMENT ************************ */
7707
7708 /* auth_lock must be held */
7709 static emlxs_auth_cfg_t *
emlxs_auth_cfg_find(emlxs_port_t * port,uint8_t * rwwpn)7710 emlxs_auth_cfg_find(emlxs_port_t *port, uint8_t *rwwpn)
7711 {
7712 emlxs_hba_t *hba = HBA;
7713 emlxs_auth_cfg_t *auth_cfg;
7714
7715 if (rwwpn) {
7716 /* lwwpn, rwwpn */
7717 auth_cfg = emlxs_auth_cfg_get(hba,
7718 (uint8_t *)&port->wwpn, (uint8_t *)rwwpn);
7719
7720 if (auth_cfg) {
7721 emlxs_auth_cfg_print(hba, auth_cfg);
7722 return (auth_cfg);
7723 }
7724 /* null, rwwpn */
7725 auth_cfg = emlxs_auth_cfg_get(hba,
7726 (uint8_t *)emlxs_null_wwn, (uint8_t *)rwwpn);
7727
7728 if (auth_cfg) {
7729 emlxs_auth_cfg_print(hba, auth_cfg);
7730 return (auth_cfg);
7731 }
7732 }
7733 /* lwwpn, null */
7734 auth_cfg = emlxs_auth_cfg_get(hba,
7735 (uint8_t *)&port->wwpn, (uint8_t *)emlxs_null_wwn);
7736
7737 if (auth_cfg) {
7738 emlxs_auth_cfg_print(hba, auth_cfg);
7739 return (auth_cfg);
7740 }
7741 /* null, null */
7742 return (&hba->auth_cfg);
7743
7744 } /* emlxs_auth_cfg_find() */
7745
7746 static void
emlxs_auth_cfg_init(emlxs_hba_t * hba)7747 emlxs_auth_cfg_init(emlxs_hba_t *hba)
7748 {
7749 emlxs_config_t *cfg = &CFG;
7750 emlxs_auth_cfg_t *auth_cfg;
7751
7752 /* Destroy old table if one exists */
7753 emlxs_auth_cfg_fini(hba);
7754
7755 mutex_enter(&hba->auth_lock);
7756
7757 /* Zero default entry */
7758 auth_cfg = &hba->auth_cfg;
7759 bzero(auth_cfg, sizeof (emlxs_auth_cfg_t));
7760 auth_cfg->next = auth_cfg;
7761 auth_cfg->prev = auth_cfg;
7762
7763 /* Configure the default entry */
7764 auth_cfg->authentication_timeout =
7765 cfg[CFG_AUTH_TMO].current;
7766 auth_cfg->authentication_mode =
7767 cfg[CFG_AUTH_MODE].current;
7768 auth_cfg->bidirectional =
7769 cfg[CFG_AUTH_BIDIR].current;
7770 auth_cfg->authentication_type_priority[0] =
7771 (cfg[CFG_AUTH_TYPE].current & 0xF000) >> 12;
7772 auth_cfg->authentication_type_priority[1] =
7773 (cfg[CFG_AUTH_TYPE].current & 0x0F00) >> 8;
7774 auth_cfg->authentication_type_priority[2] =
7775 (cfg[CFG_AUTH_TYPE].current & 0x00F0) >> 4;
7776 auth_cfg->authentication_type_priority[3] =
7777 (cfg[CFG_AUTH_TYPE].current & 0x000F);
7778 auth_cfg->hash_priority[0] =
7779 (cfg[CFG_AUTH_HASH].current & 0xF000) >> 12;
7780 auth_cfg->hash_priority[1] =
7781 (cfg[CFG_AUTH_HASH].current & 0x0F00) >> 8;
7782 auth_cfg->hash_priority[2] =
7783 (cfg[CFG_AUTH_HASH].current & 0x00F0) >> 4;
7784 auth_cfg->hash_priority[3] =
7785 (cfg[CFG_AUTH_HASH].current & 0x000F);
7786 auth_cfg->dh_group_priority[0] =
7787 (cfg[CFG_AUTH_GROUP].current & 0xF0000000) >> 28;
7788 auth_cfg->dh_group_priority[1] =
7789 (cfg[CFG_AUTH_GROUP].current & 0x0F000000) >> 24;
7790 auth_cfg->dh_group_priority[2] =
7791 (cfg[CFG_AUTH_GROUP].current & 0x00F00000) >> 20;
7792 auth_cfg->dh_group_priority[3] =
7793 (cfg[CFG_AUTH_GROUP].current & 0x000F0000) >> 16;
7794 auth_cfg->dh_group_priority[4] =
7795 (cfg[CFG_AUTH_GROUP].current & 0x0000F000) >> 12;
7796 auth_cfg->dh_group_priority[5] =
7797 (cfg[CFG_AUTH_GROUP].current & 0x00000F00) >> 8;
7798 auth_cfg->dh_group_priority[6] =
7799 (cfg[CFG_AUTH_GROUP].current & 0x000000F0) >> 4;
7800 auth_cfg->dh_group_priority[7] =
7801 (cfg[CFG_AUTH_GROUP].current & 0x0000000F);
7802 auth_cfg->reauthenticate_time_interval =
7803 cfg[CFG_AUTH_INTERVAL].current;
7804
7805 emlxs_auth_cfg_read(hba);
7806
7807 mutex_exit(&hba->auth_lock);
7808
7809 return;
7810
7811 } /* emlxs_auth_cfg_init() */
7812
7813
7814 static void
emlxs_auth_cfg_fini(emlxs_hba_t * hba)7815 emlxs_auth_cfg_fini(emlxs_hba_t *hba)
7816 {
7817 emlxs_auth_cfg_t *auth_cfg = hba->auth_cfg.next;
7818 emlxs_auth_cfg_t *next;
7819
7820 mutex_enter(&hba->auth_lock);
7821
7822 while (auth_cfg && auth_cfg != &hba->auth_cfg) {
7823 next = auth_cfg->next;
7824 emlxs_auth_cfg_destroy(hba, auth_cfg);
7825 auth_cfg = next;
7826 }
7827
7828 mutex_exit(&hba->auth_lock);
7829
7830 return;
7831
7832 } /* emlxs_auth_cfg_fini() */
7833
7834
7835 static void
emlxs_auth_cfg_print(emlxs_hba_t * hba,emlxs_auth_cfg_t * auth_cfg)7836 emlxs_auth_cfg_print(emlxs_hba_t *hba, emlxs_auth_cfg_t *auth_cfg)
7837 {
7838 emlxs_port_t *port = &PPORT;
7839
7840 char s_lwwpn[32];
7841 char s_rwwpn[32];
7842
7843 /* Create and add new entry */
7844 EMLXS_MSGF(EMLXS_CONTEXT,
7845 &emlxs_fcsp_detail_msg,
7846 "%s:%s:%x:%x:%x:%x%x%x%x:%x%x%x%x:%x%x%x%x%x%x%x%x:%x",
7847 emlxs_wwn_xlate(s_lwwpn, sizeof (s_lwwpn),
7848 (uint8_t *)&auth_cfg->local_entity),
7849 emlxs_wwn_xlate(s_rwwpn, sizeof (s_rwwpn),
7850 (uint8_t *)&auth_cfg->remote_entity),
7851 auth_cfg->authentication_timeout,
7852 auth_cfg->authentication_mode,
7853 auth_cfg->bidirectional,
7854 auth_cfg->authentication_type_priority[0],
7855 auth_cfg->authentication_type_priority[1],
7856 auth_cfg->authentication_type_priority[2],
7857 auth_cfg->authentication_type_priority[3],
7858 auth_cfg->hash_priority[0],
7859 auth_cfg->hash_priority[1],
7860 auth_cfg->hash_priority[2],
7861 auth_cfg->hash_priority[3],
7862 auth_cfg->dh_group_priority[0],
7863 auth_cfg->dh_group_priority[1],
7864 auth_cfg->dh_group_priority[2],
7865 auth_cfg->dh_group_priority[3],
7866 auth_cfg->dh_group_priority[4],
7867 auth_cfg->dh_group_priority[5],
7868 auth_cfg->dh_group_priority[6],
7869 auth_cfg->dh_group_priority[7],
7870 auth_cfg->reauthenticate_time_interval);
7871
7872 } /* emlxs_auth_cfg_print() */
7873
7874
7875 /* auth_lock must be held */
7876 static emlxs_auth_cfg_t *
emlxs_auth_cfg_get(emlxs_hba_t * hba,uint8_t * lwwpn,uint8_t * rwwpn)7877 emlxs_auth_cfg_get(emlxs_hba_t *hba, uint8_t *lwwpn, uint8_t *rwwpn)
7878 {
7879 emlxs_auth_cfg_t *auth_cfg;
7880
7881 if (!lwwpn || !rwwpn) {
7882 return (NULL);
7883 }
7884
7885 /* Check for default entry */
7886 if ((bcmp(lwwpn, emlxs_null_wwn, 8) == 0) &&
7887 (bcmp(rwwpn, emlxs_null_wwn, 8) == 0)) {
7888 return (&hba->auth_cfg);
7889 }
7890
7891 for (auth_cfg = hba->auth_cfg.next;
7892 auth_cfg != &hba->auth_cfg; auth_cfg = auth_cfg->next) {
7893 /* Find pwd entry for this local port */
7894
7895 /* Check for exact wwpn match */
7896 if (bcmp((void *)&auth_cfg->local_entity,
7897 (void *)lwwpn, 8) != 0) {
7898 continue;
7899 }
7900 /* Find pwd entry for remote port */
7901
7902 /* Check for exact wwpn match */
7903 if (bcmp((void *)&auth_cfg->remote_entity,
7904 (void *)rwwpn, 8) != 0) {
7905 continue;
7906 }
7907 return (auth_cfg);
7908 }
7909
7910 return (NULL);
7911
7912 } /* emlxs_auth_cfg_get() */
7913
7914
7915 /* auth_lock must be held */
7916 static emlxs_auth_cfg_t *
emlxs_auth_cfg_create(emlxs_hba_t * hba,uint8_t * lwwpn,uint8_t * rwwpn)7917 emlxs_auth_cfg_create(emlxs_hba_t *hba, uint8_t *lwwpn, uint8_t *rwwpn)
7918 {
7919 emlxs_auth_cfg_t *auth_cfg;
7920
7921 /* First check if entry already exists */
7922 auth_cfg = emlxs_auth_cfg_get(hba, lwwpn, rwwpn);
7923
7924 if (auth_cfg) {
7925 return (auth_cfg);
7926 }
7927 /* Allocate entry */
7928 auth_cfg = (emlxs_auth_cfg_t *)kmem_zalloc(sizeof (emlxs_auth_cfg_t),
7929 KM_NOSLEEP);
7930
7931 if (!auth_cfg) {
7932 return (NULL);
7933 }
7934 /* Add to list */
7935 auth_cfg->next = &hba->auth_cfg;
7936 auth_cfg->prev = hba->auth_cfg.prev;
7937 hba->auth_cfg.prev->next = auth_cfg;
7938 hba->auth_cfg.prev = auth_cfg;
7939 hba->auth_cfg_count++;
7940
7941 /* Initialize name pair */
7942 if (lwwpn) {
7943 bcopy((void *)lwwpn, (void *)&auth_cfg->local_entity, 8);
7944 }
7945 if (rwwpn) {
7946 bcopy((void *)rwwpn, (void *)&auth_cfg->remote_entity, 8);
7947 }
7948 auth_cfg->auth_status.auth_state = DFC_AUTH_STATE_OFF;
7949
7950 return (auth_cfg);
7951
7952 } /* emlxs_auth_cfg_create() */
7953
7954
7955 /* auth_lock must be held */
7956 static void
emlxs_auth_cfg_destroy(emlxs_hba_t * hba,emlxs_auth_cfg_t * auth_cfg)7957 emlxs_auth_cfg_destroy(emlxs_hba_t *hba, emlxs_auth_cfg_t *auth_cfg)
7958 {
7959
7960 if (!auth_cfg) {
7961 return;
7962 }
7963 if (auth_cfg == &hba->auth_cfg) {
7964 return;
7965 }
7966 /* Remove from list */
7967 auth_cfg->next->prev = auth_cfg->prev;
7968 auth_cfg->prev->next = auth_cfg->next;
7969 hba->auth_cfg_count--;
7970
7971 /* Remove node binding */
7972 if (auth_cfg->node &&
7973 auth_cfg->node->nlp_active &&
7974 (auth_cfg->node->node_dhc.parent_auth_cfg == auth_cfg)) {
7975 auth_cfg->node->node_dhc.parent_auth_cfg = NULL;
7976 }
7977 bzero(auth_cfg, sizeof (emlxs_auth_cfg_t));
7978 kmem_free(auth_cfg, sizeof (emlxs_auth_cfg_t));
7979
7980 return;
7981
7982 } /* emlxs_auth_cfg_destroy() */
7983
7984
7985 /* auth_lock must be held */
7986 static void
emlxs_auth_cfg_read(emlxs_hba_t * hba)7987 emlxs_auth_cfg_read(emlxs_hba_t *hba)
7988 {
7989 emlxs_port_t *port = &PPORT;
7990 char **arrayp;
7991 emlxs_auth_cfg_t auth_cfg;
7992 emlxs_auth_cfg_t *auth_cfg2;
7993 uint32_t cnt;
7994 uint32_t rval;
7995 char buffer[64];
7996 char *prop_str;
7997 uint32_t i;
7998
7999 /* Check for the per adapter setting */
8000 (void) snprintf(buffer, sizeof (buffer), "%s%d-auth-cfgs", DRIVER_NAME,
8001 hba->ddiinst);
8002 cnt = 0;
8003 arrayp = NULL;
8004 rval = ddi_prop_lookup_string_array(DDI_DEV_T_ANY, hba->dip,
8005 (DDI_PROP_DONTPASS),
8006 buffer, &arrayp, &cnt);
8007
8008 if ((rval != DDI_PROP_SUCCESS) || !cnt || !arrayp) {
8009 /* Check for the global setting */
8010 cnt = 0;
8011 arrayp = NULL;
8012 rval = ddi_prop_lookup_string_array(DDI_DEV_T_ANY,
8013 hba->dip, (DDI_PROP_DONTPASS),
8014 "auth-cfgs", &arrayp, &cnt);
8015 }
8016 if ((rval != DDI_PROP_SUCCESS) || !cnt || !arrayp) {
8017 return;
8018 }
8019 for (i = 0; i < cnt; i++) {
8020 prop_str = arrayp[i];
8021 if (prop_str == NULL) {
8022 break;
8023 }
8024 /* parse the string */
8025 if (emlxs_auth_cfg_parse(hba, &auth_cfg, prop_str) == 0) {
8026 EMLXS_MSGF(EMLXS_CONTEXT,
8027 &emlxs_attach_msg,
8028 "Error parsing auth_cfgs property. entry=%d", i);
8029 continue;
8030 }
8031 auth_cfg2 = emlxs_auth_cfg_create(hba,
8032 (uint8_t *)&auth_cfg.local_entity,
8033 (uint8_t *)&auth_cfg.remote_entity);
8034
8035 if (!auth_cfg2) {
8036 EMLXS_MSGF(EMLXS_CONTEXT,
8037 &emlxs_attach_msg,
8038 "Out of memory parsing auth_cfgs property. ey=%d",
8039 i);
8040 return;
8041 }
8042 auth_cfg.next = auth_cfg2->next;
8043 auth_cfg.prev = auth_cfg2->prev;
8044 bcopy((uint8_t *)&auth_cfg,
8045 (uint8_t *)auth_cfg2,
8046 sizeof (emlxs_auth_cfg_t));
8047 }
8048
8049 return;
8050
8051 } /* emlxs_auth_cfg_read() */
8052
8053
8054 /* auth_lock must be held */
8055 static uint32_t
emlxs_auth_cfg_parse(emlxs_hba_t * hba,emlxs_auth_cfg_t * auth_cfg,char * prop_str)8056 emlxs_auth_cfg_parse(
8057 emlxs_hba_t *hba,
8058 emlxs_auth_cfg_t *auth_cfg,
8059 char *prop_str)
8060 {
8061 emlxs_port_t *port = &PPORT;
8062 emlxs_config_t *cfg = &CFG;
8063 uint32_t errors = 0;
8064 uint32_t c1;
8065 uint8_t *np;
8066 uint32_t j;
8067 uint32_t i;
8068 uint32_t sum;
8069 char *s;
8070
8071 s = prop_str;
8072 bzero(auth_cfg, sizeof (emlxs_auth_cfg_t));
8073
8074 /* Read local wwpn */
8075 np = (uint8_t *)&auth_cfg->local_entity;
8076 for (j = 0; j < 8; j++) {
8077 c1 = *s++;
8078 if ((c1 >= '0') && (c1 <= '9')) {
8079 sum = ((c1 - '0') << 4);
8080 } else if ((c1 >= 'a') && (c1 <= 'f')) {
8081 sum = ((c1 - 'a' + 10) << 4);
8082 } else if ((c1 >= 'A') && (c1 <= 'F')) {
8083 sum = ((c1 - 'A' + 10) << 4);
8084 } else {
8085 EMLXS_MSGF(EMLXS_CONTEXT,
8086 &emlxs_attach_debug_msg,
8087 "Cfg err:Invalid LWWPN found. byte=%d hi_nibble=%c",
8088 j, c1);
8089 errors++;
8090 }
8091
8092 c1 = *s++;
8093 if ((c1 >= '0') && (c1 <= '9')) {
8094 sum |= (c1 - '0');
8095 } else if ((c1 >= 'a') && (c1 <= 'f')) {
8096 sum |= (c1 - 'a' + 10);
8097 } else if ((c1 >= 'A') && (c1 <= 'F')) {
8098 sum |= (c1 - 'A' + 10);
8099 } else {
8100 EMLXS_MSGF(EMLXS_CONTEXT,
8101 &emlxs_attach_debug_msg,
8102 "Cfg err: Invalid LWWPN found. %d %c",
8103 j, c1);
8104 errors++;
8105 }
8106
8107 *np++ = (uint8_t)sum;
8108 }
8109
8110 if (*s++ != ':') {
8111 EMLXS_MSGF(EMLXS_CONTEXT,
8112 &emlxs_attach_debug_msg,
8113 "Cfg err: Invalid delimiter after LWWPN.");
8114 goto out;
8115 }
8116 /* Read remote wwpn */
8117 np = (uint8_t *)&auth_cfg->remote_entity;
8118 for (j = 0; j < 8; j++) {
8119 c1 = *s++;
8120 if ((c1 >= '0') && (c1 <= '9')) {
8121 sum = ((c1 - '0') << 4);
8122 } else if ((c1 >= 'a') && (c1 <= 'f')) {
8123 sum = ((c1 - 'a' + 10) << 4);
8124 } else if ((c1 >= 'A') && (c1 <= 'F')) {
8125 sum = ((c1 - 'A' + 10) << 4);
8126 } else {
8127 EMLXS_MSGF(EMLXS_CONTEXT,
8128 &emlxs_attach_debug_msg,
8129 "Cfg err: Invalid RWWPN found.byte=%d hi_nibble=%c",
8130 j, c1);
8131 errors++;
8132 }
8133
8134 c1 = *s++;
8135 if ((c1 >= '0') && (c1 <= '9')) {
8136 sum |= (c1 - '0');
8137 } else if ((c1 >= 'a') && (c1 <= 'f')) {
8138 sum |= (c1 - 'a' + 10);
8139 } else if ((c1 >= 'A') && (c1 <= 'F')) {
8140 sum |= (c1 - 'A' + 10);
8141 } else {
8142 EMLXS_MSGF(EMLXS_CONTEXT,
8143 &emlxs_attach_debug_msg,
8144 "Cfg err: Invalid RWWPN found. %d %c",
8145 j, c1);
8146 errors++;
8147 }
8148
8149 *np++ = (uint8_t)sum;
8150 }
8151
8152 if (*s++ != ':') {
8153 EMLXS_MSGF(EMLXS_CONTEXT,
8154 &emlxs_attach_debug_msg,
8155 "Cfg err: Invalid delimiter after RWWPN.");
8156 goto out;
8157 }
8158 /* Read auth_tov (%x) */
8159 sum = 0;
8160 do {
8161 c1 = *s++;
8162 if ((c1 >= '0') && (c1 <= '9')) {
8163 sum = (sum << 4) + (c1 - '0');
8164 } else if ((c1 >= 'a') && (c1 <= 'f')) {
8165 sum = (sum << 4) + (c1 - 'a' + 10);
8166 } else if ((c1 >= 'A') && (c1 <= 'F')) {
8167 sum = (sum << 4) + (c1 - 'A' + 10);
8168 } else {
8169 EMLXS_MSGF(EMLXS_CONTEXT,
8170 &emlxs_attach_debug_msg,
8171 "Cfg err: Invalid auth_tov found. c=%c sum=%d",
8172 c1, sum);
8173
8174 errors++;
8175 }
8176
8177 } while (*s != ':' && *s != 0);
8178 auth_cfg->authentication_timeout = sum;
8179
8180 if (*s++ != ':') {
8181 EMLXS_MSGF(EMLXS_CONTEXT,
8182 &emlxs_attach_debug_msg,
8183 "Cfg err: Invalid delimiter after auth_tov.");
8184 goto out;
8185 }
8186 /* Read auth_mode */
8187 sum = 0;
8188 do {
8189 c1 = *s++;
8190 if ((c1 >= '0') && (c1 <= '9')) {
8191 sum = (sum << 4) + (c1 - '0');
8192 } else if ((c1 >= 'a') && (c1 <= 'f')) {
8193 sum = (sum << 4) + (c1 - 'a' + 10);
8194 } else if ((c1 >= 'A') && (c1 <= 'F')) {
8195 sum = (sum << 4) + (c1 - 'A' + 10);
8196 } else {
8197 EMLXS_MSGF(EMLXS_CONTEXT,
8198 &emlxs_attach_debug_msg,
8199 "Cfg err: Invalid auth_mode found. c=%c sum=%d",
8200 c1, sum);
8201
8202 errors++;
8203 }
8204
8205 } while (*s != ':' && *s != 0);
8206 auth_cfg->authentication_mode = sum;
8207
8208 if (*s++ != ':') {
8209 EMLXS_MSGF(EMLXS_CONTEXT,
8210 &emlxs_attach_debug_msg,
8211 "Config error: Invalid delimiter after auth_mode.");
8212 goto out;
8213 }
8214 /* Read auth_bidir */
8215 sum = 0;
8216 do {
8217 c1 = *s++;
8218 if ((c1 >= '0') && (c1 <= '9')) {
8219 sum = (sum << 4) + (c1 - '0');
8220 } else if ((c1 >= 'a') && (c1 <= 'f')) {
8221 sum = (sum << 4) + (c1 - 'a' + 10);
8222 } else if ((c1 >= 'A') && (c1 <= 'F')) {
8223 sum = (sum << 4) + (c1 - 'A' + 10);
8224 } else {
8225 EMLXS_MSGF(EMLXS_CONTEXT,
8226 &emlxs_attach_debug_msg,
8227 "Cfg err: Invalid auth_bidir found. c=%c sum=%d",
8228 c1, sum);
8229
8230 errors++;
8231 }
8232
8233 } while (*s != ':' && *s != 0);
8234 auth_cfg->bidirectional = sum;
8235
8236 if (*s++ != ':') {
8237 EMLXS_MSGF(EMLXS_CONTEXT,
8238 &emlxs_attach_debug_msg,
8239 "Cfg err: Invalid delimiter after auth_bidir.");
8240 goto out;
8241 }
8242 /* Read type_priority[4] */
8243 for (i = 0; i < 4; i++) {
8244 c1 = *s++;
8245 if ((c1 >= '0') && (c1 <= '9')) {
8246 sum = (c1 - '0');
8247 } else if ((c1 >= 'a') && (c1 <= 'f')) {
8248 sum = (c1 - 'a' + 10);
8249 } else if ((c1 >= 'A') && (c1 <= 'F')) {
8250 sum = (c1 - 'A' + 10);
8251 } else {
8252 EMLXS_MSGF(EMLXS_CONTEXT,
8253 &emlxs_attach_debug_msg,
8254 "Cfg err: Invalid type_pty[%d] found. c=%c sum=%d",
8255 i, c1, sum);
8256
8257 errors++;
8258 }
8259
8260 auth_cfg->authentication_type_priority[i] = sum;
8261 }
8262
8263 if (*s++ != ':') {
8264 EMLXS_MSGF(EMLXS_CONTEXT,
8265 &emlxs_attach_debug_msg,
8266 "Cfg err: Invalid delimiter after type_priority.");
8267
8268 goto out;
8269 }
8270 /* Read hash_priority[4] */
8271 for (i = 0; i < 4; i++) {
8272 c1 = *s++;
8273 if ((c1 >= '0') && (c1 <= '9')) {
8274 sum = (c1 - '0');
8275 } else if ((c1 >= 'a') && (c1 <= 'f')) {
8276 sum = (c1 - 'a' + 10);
8277 } else if ((c1 >= 'A') && (c1 <= 'F')) {
8278 sum = (c1 - 'A' + 10);
8279 } else {
8280 EMLXS_MSGF(EMLXS_CONTEXT,
8281 &emlxs_attach_debug_msg,
8282 "Cfg err: Invalid hash_priority[%d] fd. %c %d",
8283 i, c1, sum);
8284
8285 errors++;
8286 }
8287
8288 auth_cfg->hash_priority[i] = sum;
8289 }
8290
8291 if (*s++ != ':') {
8292 EMLXS_MSGF(EMLXS_CONTEXT,
8293 &emlxs_attach_debug_msg,
8294 "Cfg err: Invalid delimiter after hash_priority.");
8295
8296 goto out;
8297 }
8298 /* Read group_priority[8] */
8299 for (i = 0; i < 8; i++) {
8300 c1 = *s++;
8301 if ((c1 >= '0') && (c1 <= '9')) {
8302 sum = (c1 - '0');
8303 } else if ((c1 >= 'a') && (c1 <= 'f')) {
8304 sum = (c1 - 'a' + 10);
8305 } else if ((c1 >= 'A') && (c1 <= 'F')) {
8306 sum = (c1 - 'A' + 10);
8307 } else {
8308 EMLXS_MSGF(EMLXS_CONTEXT,
8309 &emlxs_attach_debug_msg,
8310 "Cfg err: Invalid group_priority[%d] fd. %c %d",
8311 i, c1, sum);
8312
8313 errors++;
8314 }
8315
8316 auth_cfg->dh_group_priority[i] = sum;
8317 }
8318
8319 if (*s++ != ':') {
8320 EMLXS_MSGF(EMLXS_CONTEXT,
8321 &emlxs_attach_debug_msg,
8322 "Cfg err: Invalid delimiter after group_priority.");
8323 goto out;
8324 }
8325 /* Read reauth_tov */
8326 sum = 0;
8327 do {
8328 c1 = *s++;
8329 if ((c1 >= '0') && (c1 <= '9')) {
8330 sum = (sum << 4) + (c1 - '0');
8331 } else if ((c1 >= 'a') && (c1 <= 'f')) {
8332 sum = (sum << 4) + (c1 - 'a' + 10);
8333 } else if ((c1 >= 'A') && (c1 <= 'F')) {
8334 sum = (sum << 4) + (c1 - 'A' + 10);
8335 } else {
8336 EMLXS_MSGF(EMLXS_CONTEXT,
8337 &emlxs_attach_debug_msg,
8338 "Cfg err: Invalid reauth_tov found. c=%c sum=%d",
8339 c1, sum);
8340
8341 errors++;
8342 }
8343
8344 } while (*s != ':' && *s != 0);
8345 auth_cfg->reauthenticate_time_interval = sum;
8346
8347 if (errors) {
8348 goto out;
8349 }
8350 /* Verify values */
8351
8352 /* Check authentication_timeout */
8353 if (auth_cfg->authentication_timeout < cfg[CFG_AUTH_TMO].low) {
8354 auth_cfg->authentication_timeout = cfg[CFG_AUTH_TMO].current;
8355 } else if (auth_cfg->authentication_timeout > cfg[CFG_AUTH_TMO].hi) {
8356 auth_cfg->authentication_timeout = cfg[CFG_AUTH_TMO].current;
8357 }
8358 /* Check authentication_mode */
8359 if (auth_cfg->authentication_mode < cfg[CFG_AUTH_MODE].low) {
8360 auth_cfg->authentication_mode = cfg[CFG_AUTH_MODE].current;
8361 } else if (auth_cfg->authentication_mode > cfg[CFG_AUTH_MODE].hi) {
8362 auth_cfg->authentication_mode = cfg[CFG_AUTH_MODE].current;
8363 }
8364 /* Check bidirectional */
8365 if (auth_cfg->bidirectional < cfg[CFG_AUTH_BIDIR].low) {
8366 auth_cfg->bidirectional = cfg[CFG_AUTH_BIDIR].current;
8367 } else if (auth_cfg->bidirectional > cfg[CFG_AUTH_BIDIR].hi) {
8368 auth_cfg->bidirectional = cfg[CFG_AUTH_BIDIR].current;
8369 }
8370 /* Check authentication_type_priority and hash_priority */
8371 for (i = 0; i < 4; i++) {
8372 if (auth_cfg->authentication_type_priority[i] >
8373 DFC_AUTH_TYPE_MAX) {
8374 /* Set to current default */
8375 auth_cfg->authentication_type_priority[i] =
8376 hba->auth_cfg.authentication_type_priority[i];
8377 }
8378 if (auth_cfg->hash_priority[i] > DFC_AUTH_HASH_MAX) {
8379 /* Set to current default */
8380 auth_cfg->hash_priority[i] =
8381 hba->auth_cfg.hash_priority[i];
8382 }
8383 }
8384
8385 /* Check dh_group_priority */
8386 for (i = 0; i < 8; i++) {
8387 if (auth_cfg->dh_group_priority[i] > DFC_AUTH_GROUP_MAX) {
8388 /* Set to current default */
8389 auth_cfg->dh_group_priority[i] =
8390 hba->auth_cfg.dh_group_priority[i];
8391 }
8392 }
8393
8394 /* Check reauthenticate_time_interval */
8395 if (auth_cfg->reauthenticate_time_interval <
8396 cfg[CFG_AUTH_INTERVAL].low) {
8397 auth_cfg->reauthenticate_time_interval =
8398 cfg[CFG_AUTH_INTERVAL].current;
8399 } else if (auth_cfg->reauthenticate_time_interval >
8400 cfg[CFG_AUTH_INTERVAL].hi) {
8401 auth_cfg->reauthenticate_time_interval =
8402 cfg[CFG_AUTH_INTERVAL].current;
8403 }
8404 emlxs_auth_cfg_print(hba, auth_cfg);
8405
8406 out:
8407
8408 if (errors) {
8409 bzero(auth_cfg, sizeof (emlxs_auth_cfg_t));
8410 return (0);
8411 }
8412 return (1);
8413
8414 } /* emlxs_auth_cfg_parse() */
8415
8416
8417 /* **************************** AUTH KEY MANAGEMENT ************************* */
8418
8419 /* auth_lock must be held */
8420 extern emlxs_auth_key_t *
emlxs_auth_key_find(emlxs_port_t * port,uint8_t * rwwpn)8421 emlxs_auth_key_find(emlxs_port_t *port, uint8_t *rwwpn)
8422 {
8423 emlxs_hba_t *hba = HBA;
8424 emlxs_auth_key_t *auth_key;
8425
8426 if (rwwpn) {
8427 /* lwwpn, rwwpn */
8428 auth_key = emlxs_auth_key_get(hba,
8429 (uint8_t *)&port->wwpn, (uint8_t *)rwwpn);
8430
8431 if (auth_key) {
8432 emlxs_auth_key_print(hba, auth_key);
8433 return (auth_key);
8434 }
8435 /* null, rwwpn */
8436 auth_key = emlxs_auth_key_get(hba,
8437 (uint8_t *)emlxs_null_wwn, (uint8_t *)rwwpn);
8438
8439 if (auth_key) {
8440 emlxs_auth_key_print(hba, auth_key);
8441 return (auth_key);
8442 }
8443 }
8444 /* lwwpn, null */
8445 auth_key = emlxs_auth_key_get(hba,
8446 (uint8_t *)&port->wwpn, (uint8_t *)emlxs_null_wwn);
8447
8448 if (auth_key) {
8449 emlxs_auth_key_print(hba, auth_key);
8450 return (auth_key);
8451 }
8452 return (NULL);
8453
8454 } /* emlxs_auth_key_find() */
8455
8456
8457 static void
emlxs_auth_key_init(emlxs_hba_t * hba)8458 emlxs_auth_key_init(emlxs_hba_t *hba)
8459 {
8460 emlxs_auth_key_t *auth_key;
8461
8462 /* Destroy old table if one exists */
8463 emlxs_auth_key_fini(hba);
8464
8465 mutex_enter(&hba->auth_lock);
8466
8467 /* Zero default entry */
8468 auth_key = &hba->auth_key;
8469 bzero(auth_key, sizeof (emlxs_auth_key_t));
8470 auth_key->next = auth_key;
8471 auth_key->prev = auth_key;
8472
8473 /* Configure the default entry */
8474 auth_key->local_password_type = PASSWORD_TYPE_IGNORE;
8475 auth_key->remote_password_type = PASSWORD_TYPE_IGNORE;
8476
8477 emlxs_auth_key_read(hba);
8478
8479 mutex_exit(&hba->auth_lock);
8480
8481 return;
8482
8483 } /* emlxs_auth_key_init() */
8484
8485
8486 static void
emlxs_auth_key_fini(emlxs_hba_t * hba)8487 emlxs_auth_key_fini(emlxs_hba_t *hba)
8488 {
8489 emlxs_auth_key_t *auth_key = hba->auth_key.next;
8490 emlxs_auth_key_t *next;
8491
8492 mutex_enter(&hba->auth_lock);
8493
8494 while (auth_key && auth_key != &hba->auth_key) {
8495 next = auth_key->next;
8496 emlxs_auth_key_destroy(hba, auth_key);
8497 auth_key = next;
8498 }
8499
8500 mutex_exit(&hba->auth_lock);
8501
8502 return;
8503
8504 } /* emlxs_auth_key_fini() */
8505
8506
8507 static void
emlxs_auth_key_print(emlxs_hba_t * hba,emlxs_auth_key_t * auth_key)8508 emlxs_auth_key_print(emlxs_hba_t *hba, emlxs_auth_key_t *auth_key)
8509 {
8510 emlxs_port_t *port = &PPORT;
8511 char s_lwwpn[32];
8512 char s_rwwpn[32];
8513
8514 EMLXS_MSGF(EMLXS_CONTEXT,
8515 &emlxs_fcsp_detail_msg,
8516 "auth-key> %s:%s:%x:*%d chars*:%x:*%d chars*",
8517 emlxs_wwn_xlate(s_lwwpn, sizeof (s_lwwpn),
8518 (uint8_t *)&auth_key->local_entity),
8519 emlxs_wwn_xlate(s_rwwpn, sizeof (s_rwwpn),
8520 (uint8_t *)&auth_key->remote_entity),
8521 auth_key->local_password_type, auth_key->local_password_length,
8522 auth_key->remote_password_type, auth_key->remote_password_length);
8523
8524 return;
8525
8526 } /* emlxs_auth_key_print() */
8527
8528
8529 /* auth_lock must be held */
8530 static emlxs_auth_key_t *
emlxs_auth_key_get(emlxs_hba_t * hba,uint8_t * lwwpn,uint8_t * rwwpn)8531 emlxs_auth_key_get(emlxs_hba_t *hba, uint8_t *lwwpn, uint8_t *rwwpn)
8532 {
8533 emlxs_auth_key_t *auth_key;
8534
8535 if (!lwwpn || !rwwpn) {
8536 return (NULL);
8537 }
8538 /* Check for default entry */
8539 if ((bcmp(lwwpn, emlxs_null_wwn, 8) == 0) &&
8540 (bcmp(rwwpn, emlxs_null_wwn, 8) == 0)) {
8541 return (&hba->auth_key);
8542 }
8543 for (auth_key = hba->auth_key.next; auth_key !=
8544 &hba->auth_key; auth_key = auth_key->next) {
8545 /* Find pwd entry for this local port */
8546
8547 /* Check for exact wwpn match */
8548 if (bcmp((void *)&auth_key->local_entity,
8549 (void *)lwwpn, 8) != 0) {
8550 continue;
8551 }
8552 /* Find pwd entry for remote port */
8553
8554 /* Check for exact wwpn match */
8555 if (bcmp((void *)&auth_key->remote_entity,
8556 (void *)rwwpn, 8) != 0) {
8557 continue;
8558 }
8559 return (auth_key);
8560 }
8561
8562 return (NULL);
8563
8564 } /* emlxs_auth_key_get() */
8565
8566
8567 /* auth_lock must be held */
8568 static emlxs_auth_key_t *
emlxs_auth_key_create(emlxs_hba_t * hba,uint8_t * lwwpn,uint8_t * rwwpn)8569 emlxs_auth_key_create(emlxs_hba_t *hba, uint8_t *lwwpn, uint8_t *rwwpn)
8570 {
8571 emlxs_auth_key_t *auth_key;
8572
8573 /* First check if entry already exists */
8574 auth_key = emlxs_auth_key_get(hba, lwwpn, rwwpn);
8575
8576 if (auth_key) {
8577 return (auth_key);
8578 }
8579 /* Allocate entry */
8580 auth_key = (emlxs_auth_key_t *)kmem_zalloc(sizeof (emlxs_auth_key_t),
8581 KM_NOSLEEP);
8582
8583 if (!auth_key) {
8584 return (NULL);
8585 }
8586 /* Initialize name pair */
8587 if (lwwpn) {
8588 bcopy((void *)lwwpn, (void *)&auth_key->local_entity, 8);
8589 }
8590 if (rwwpn) {
8591 bcopy((void *)rwwpn, (void *)&auth_key->remote_entity, 8);
8592 }
8593 /* Initialize type */
8594 auth_key->local_password_type = PASSWORD_TYPE_IGNORE;
8595 auth_key->remote_password_type = PASSWORD_TYPE_IGNORE;
8596
8597 /* Add to list */
8598 auth_key->next = &hba->auth_key;
8599 auth_key->prev = hba->auth_key.prev;
8600 hba->auth_key.prev->next = auth_key;
8601 hba->auth_key.prev = auth_key;
8602 hba->auth_key_count++;
8603
8604 return (auth_key);
8605
8606 } /* emlxs_auth_key_create() */
8607
8608
8609 /* auth_lock must be held */
8610 static void
emlxs_auth_key_destroy(emlxs_hba_t * hba,emlxs_auth_key_t * auth_key)8611 emlxs_auth_key_destroy(emlxs_hba_t *hba, emlxs_auth_key_t *auth_key)
8612 {
8613
8614 if (!auth_key) {
8615 return;
8616 }
8617 if (auth_key == &hba->auth_key) {
8618 return;
8619 }
8620 /* Remove from list */
8621 auth_key->next->prev = auth_key->prev;
8622 auth_key->prev->next = auth_key->next;
8623 hba->auth_key_count--;
8624
8625 /* Remove node binding */
8626 if (auth_key->node &&
8627 auth_key->node->nlp_active &&
8628 (auth_key->node->node_dhc.parent_auth_key == auth_key)) {
8629 auth_key->node->node_dhc.parent_auth_key = NULL;
8630 }
8631 bzero(auth_key, sizeof (emlxs_auth_key_t));
8632 kmem_free(auth_key, sizeof (emlxs_auth_key_t));
8633
8634 return;
8635
8636 } /* emlxs_auth_key_destroy() */
8637
8638
8639 /* auth_lock must be held */
8640 static void
emlxs_auth_key_read(emlxs_hba_t * hba)8641 emlxs_auth_key_read(emlxs_hba_t *hba)
8642 {
8643 emlxs_port_t *port = &PPORT;
8644 char **arrayp;
8645 emlxs_auth_key_t auth_key;
8646 emlxs_auth_key_t *auth_key2;
8647 uint32_t cnt;
8648 uint32_t rval;
8649 char buffer[64];
8650 char *prop_str;
8651 uint32_t i;
8652
8653 /* Check for the per adapter setting */
8654 (void) snprintf(buffer, sizeof (buffer), "%s%d-auth-keys", DRIVER_NAME,
8655 hba->ddiinst);
8656 cnt = 0;
8657 arrayp = NULL;
8658 rval = ddi_prop_lookup_string_array(DDI_DEV_T_ANY, hba->dip,
8659 (DDI_PROP_DONTPASS),
8660 buffer, &arrayp, &cnt);
8661
8662 if ((rval != DDI_PROP_SUCCESS) || !cnt || !arrayp) {
8663 /* Check for the global setting */
8664 cnt = 0;
8665 arrayp = NULL;
8666 rval = ddi_prop_lookup_string_array(DDI_DEV_T_ANY, hba->dip,
8667 (DDI_PROP_DONTPASS),
8668 "auth-keys", &arrayp, &cnt);
8669 }
8670 if ((rval != DDI_PROP_SUCCESS) || !cnt || !arrayp) {
8671 return;
8672 }
8673 for (i = 0; i < cnt; i++) {
8674 prop_str = arrayp[i];
8675 if (prop_str == NULL) {
8676 break;
8677 }
8678 /* parse the string */
8679 if (emlxs_auth_key_parse(hba, &auth_key, prop_str) == 0) {
8680 EMLXS_MSGF(EMLXS_CONTEXT,
8681 &emlxs_attach_msg,
8682 "Error parsing auth_keys property. entry=%d", i);
8683 continue;
8684 }
8685 auth_key2 = emlxs_auth_key_create(hba,
8686 (uint8_t *)&auth_key.local_entity,
8687 (uint8_t *)&auth_key.remote_entity);
8688
8689 if (!auth_key2) {
8690 EMLXS_MSGF(EMLXS_CONTEXT,
8691 &emlxs_attach_msg,
8692 "Out of memory parsing auth_keys property. %d",
8693 i);
8694 return;
8695 }
8696 auth_key.next = auth_key2->next;
8697 auth_key.prev = auth_key2->prev;
8698 bcopy((uint8_t *)&auth_key,
8699 (uint8_t *)auth_key2, sizeof (emlxs_auth_key_t));
8700 }
8701
8702 return;
8703
8704 } /* emlxs_auth_key_read() */
8705
8706
8707 /* auth_lock must be held */
8708 static uint32_t
emlxs_auth_key_parse(emlxs_hba_t * hba,emlxs_auth_key_t * auth_key,char * prop_str)8709 emlxs_auth_key_parse(
8710 emlxs_hba_t *hba,
8711 emlxs_auth_key_t *auth_key,
8712 char *prop_str)
8713 {
8714 emlxs_port_t *port = &PPORT;
8715 uint32_t errors = 0;
8716 uint32_t c1;
8717 uint8_t *np;
8718 uint32_t j;
8719 uint32_t sum;
8720 char *s;
8721
8722 s = prop_str;
8723 bzero(auth_key, sizeof (emlxs_auth_key_t));
8724
8725 /* Read local wwpn */
8726 np = (uint8_t *)&auth_key->local_entity;
8727 for (j = 0; j < 8; j++) {
8728 c1 = *s++;
8729 if ((c1 >= '0') && (c1 <= '9')) {
8730 sum = ((c1 - '0') << 4);
8731 } else if ((c1 >= 'a') && (c1 <= 'f')) {
8732 sum = ((c1 - 'a' + 10) << 4);
8733 } else if ((c1 >= 'A') && (c1 <= 'F')) {
8734 sum = ((c1 - 'A' + 10) << 4);
8735 } else {
8736 EMLXS_MSGF(EMLXS_CONTEXT,
8737 &emlxs_attach_debug_msg,
8738 "Cfg err: Invalid LWWPN found. %d %c",
8739 j, c1);
8740 errors++;
8741 }
8742
8743 c1 = *s++;
8744 if ((c1 >= '0') && (c1 <= '9')) {
8745 sum |= (c1 - '0');
8746 } else if ((c1 >= 'a') && (c1 <= 'f')) {
8747 sum |= (c1 - 'a' + 10);
8748 } else if ((c1 >= 'A') && (c1 <= 'F')) {
8749 sum |= (c1 - 'A' + 10);
8750 } else {
8751 EMLXS_MSGF(EMLXS_CONTEXT,
8752 &emlxs_attach_debug_msg,
8753 "Cfg err: Invalid LWWPN found. %d %c",
8754 j, c1);
8755 errors++;
8756 }
8757
8758 *np++ = (uint8_t)sum;
8759 }
8760
8761 if (*s++ != ':') {
8762 EMLXS_MSGF(EMLXS_CONTEXT,
8763 &emlxs_attach_debug_msg,
8764 "Cfg err: Invalid delimiter after LWWPN.");
8765 goto out;
8766 }
8767 /* Read remote wwpn */
8768 np = (uint8_t *)&auth_key->remote_entity;
8769 for (j = 0; j < 8; j++) {
8770 c1 = *s++;
8771 if ((c1 >= '0') && (c1 <= '9')) {
8772 sum = ((c1 - '0') << 4);
8773 } else if ((c1 >= 'a') && (c1 <= 'f')) {
8774 sum = ((c1 - 'a' + 10) << 4);
8775 } else if ((c1 >= 'A') && (c1 <= 'F')) {
8776 sum = ((c1 - 'A' + 10) << 4);
8777 } else {
8778 EMLXS_MSGF(EMLXS_CONTEXT,
8779 &emlxs_attach_debug_msg,
8780 "Cfg err: Invalid RWWPN found.%d %c",
8781 j, c1);
8782 errors++;
8783 }
8784
8785 c1 = *s++;
8786 if ((c1 >= '0') && (c1 <= '9')) {
8787 sum |= (c1 - '0');
8788 } else if ((c1 >= 'a') && (c1 <= 'f')) {
8789 sum |= (c1 - 'a' + 10);
8790 } else if ((c1 >= 'A') && (c1 <= 'F')) {
8791 sum |= (c1 - 'A' + 10);
8792 } else {
8793 EMLXS_MSGF(EMLXS_CONTEXT,
8794 &emlxs_attach_debug_msg,
8795 "Cfg err: Invalid RWWPN found. %d %c",
8796 j, c1);
8797 errors++;
8798 }
8799
8800 *np++ = (uint8_t)sum;
8801 }
8802
8803 if (*s++ != ':') {
8804 EMLXS_MSGF(EMLXS_CONTEXT,
8805 &emlxs_attach_debug_msg,
8806 "Cfg err: Invalid delimiter after RWWPN.");
8807 goto out;
8808 }
8809 /* Read lpwd type (%x) */
8810 sum = 0;
8811 do {
8812 c1 = *s++;
8813 if ((c1 >= '0') && (c1 <= '9')) {
8814 sum = (sum << 4) + (c1 - '0');
8815 } else if ((c1 >= 'a') && (c1 <= 'f')) {
8816 sum = (sum << 4) + (c1 - 'a' + 10);
8817 } else if ((c1 >= 'A') && (c1 <= 'F')) {
8818 sum = (sum << 4) + (c1 - 'A' + 10);
8819 } else {
8820 EMLXS_MSGF(EMLXS_CONTEXT,
8821 &emlxs_attach_debug_msg,
8822 "Cfg err: Invalid lpwd type found. %c %d",
8823 c1, sum);
8824
8825 errors++;
8826 }
8827
8828 } while (*s != ':' && *s != 0);
8829 auth_key->local_password_type = (uint16_t)sum;
8830
8831 if (*s++ != ':') {
8832 EMLXS_MSGF(EMLXS_CONTEXT,
8833 &emlxs_attach_debug_msg,
8834 "Cfg err: Invalid delimiter after lpwd type.");
8835 goto out;
8836 }
8837 /* Read lpwd */
8838 np = (uint8_t *)&auth_key->local_password;
8839 j = 0;
8840 switch (auth_key->local_password_type) {
8841 case 1: /* ACSII */
8842 while (*s != ':' && *s != 0) {
8843 *np++ = *s++;
8844 j++;
8845 }
8846 break;
8847
8848 case 2: /* Hex */
8849 do {
8850 c1 = *s++;
8851 if ((c1 >= '0') && (c1 <= '9')) {
8852 sum = ((c1 - '0') << 4);
8853 } else if ((c1 >= 'a') && (c1 <= 'f')) {
8854 sum = ((c1 - 'a' + 10) << 4);
8855 } else if ((c1 >= 'A') && (c1 <= 'F')) {
8856 sum = ((c1 - 'A' + 10) << 4);
8857 } else {
8858 EMLXS_MSGF(EMLXS_CONTEXT,
8859 &emlxs_attach_debug_msg,
8860 "Cfg err: Invalid lpwd found. %d %c",
8861 j, c1);
8862 errors++;
8863 }
8864
8865 c1 = *s++;
8866 if ((c1 >= '0') && (c1 <= '9')) {
8867 sum |= (c1 - '0');
8868 } else if ((c1 >= 'a') && (c1 <= 'f')) {
8869 sum |= (c1 - 'a' + 10);
8870 } else if ((c1 >= 'A') && (c1 <= 'F')) {
8871 sum |= (c1 - 'A' + 10);
8872 } else {
8873 EMLXS_MSGF(EMLXS_CONTEXT,
8874 &emlxs_attach_debug_msg,
8875 "Cfg err: Invalid lpwd found. %d %c",
8876 j, c1);
8877 errors++;
8878 }
8879
8880 *np++ = (uint8_t)sum;
8881 j++;
8882
8883 } while (*s != ':' && *s != 0);
8884
8885 break;
8886
8887 case 0: /* Ignore */
8888 case 3: /* Ignore */
8889 break;
8890
8891 default:
8892 EMLXS_MSGF(EMLXS_CONTEXT,
8893 &emlxs_attach_debug_msg,
8894 "Config error: Invalid lpwd type found. type=%x",
8895 auth_key->local_password_type);
8896
8897 errors++;
8898 goto out;
8899 }
8900 auth_key->local_password_length = (uint16_t)j;
8901
8902 if (*s++ != ':') {
8903 EMLXS_MSGF(EMLXS_CONTEXT,
8904 &emlxs_attach_debug_msg,
8905 "Config error: Invalid delimiter after lpwd.");
8906 goto out;
8907 }
8908 /* Read rpwd type (%x) */
8909 sum = 0;
8910 do {
8911 c1 = *s++;
8912 if ((c1 >= '0') && (c1 <= '9')) {
8913 sum = (sum << 4) + (c1 - '0');
8914 } else if ((c1 >= 'a') && (c1 <= 'f')) {
8915 sum = (sum << 4) + (c1 - 'a' + 10);
8916 } else if ((c1 >= 'A') && (c1 <= 'F')) {
8917 sum = (sum << 4) + (c1 - 'A' + 10);
8918 } else {
8919 EMLXS_MSGF(EMLXS_CONTEXT,
8920 &emlxs_attach_debug_msg,
8921 "Config error: Invalid rpwd type found. %c %d",
8922 c1, sum);
8923
8924 errors++;
8925 }
8926
8927 } while (*s != ':' && *s != 0);
8928 auth_key->remote_password_type = (uint16_t)sum;
8929
8930 if (*s++ != ':') {
8931 EMLXS_MSGF(EMLXS_CONTEXT,
8932 &emlxs_attach_debug_msg,
8933 "Config error: Invalid delimiter after rpwd type.");
8934 goto out;
8935 }
8936 /* Read rpwd */
8937 np = (uint8_t *)&auth_key->remote_password;
8938 j = 0;
8939 switch (auth_key->remote_password_type) {
8940 case 1: /* ACSII */
8941 while (*s != ':' && *s != 0) {
8942 *np++ = *s++;
8943 j++;
8944 }
8945 break;
8946
8947 case 2: /* Hex */
8948 do {
8949 c1 = *s++;
8950 if ((c1 >= '0') && (c1 <= '9')) {
8951 sum = ((c1 - '0') << 4);
8952 } else if ((c1 >= 'a') && (c1 <= 'f')) {
8953 sum = ((c1 - 'a' + 10) << 4);
8954 } else if ((c1 >= 'A') && (c1 <= 'F')) {
8955 sum = ((c1 - 'A' + 10) << 4);
8956 } else {
8957 EMLXS_MSGF(EMLXS_CONTEXT,
8958 &emlxs_attach_debug_msg,
8959 "Cfg err: Invalid rpwd found. %d %c",
8960 j, c1);
8961 errors++;
8962 }
8963
8964 c1 = *s++;
8965 if ((c1 >= '0') && (c1 <= '9')) {
8966 sum |= (c1 - '0');
8967 } else if ((c1 >= 'a') && (c1 <= 'f')) {
8968 sum |= (c1 - 'a' + 10);
8969 } else if ((c1 >= 'A') && (c1 <= 'F')) {
8970 sum |= (c1 - 'A' + 10);
8971 } else {
8972 EMLXS_MSGF(EMLXS_CONTEXT,
8973 &emlxs_attach_debug_msg,
8974 "Cfg err: Invalid rpwd found. %d %c",
8975 j, c1);
8976 errors++;
8977 }
8978
8979 *np++ = (uint8_t)sum;
8980 j++;
8981
8982 } while (*s != ':' && *s != 0);
8983
8984 break;
8985
8986 case 0: /* Ignore */
8987 case 3: /* Ignore */
8988 break;
8989
8990 default:
8991 EMLXS_MSGF(EMLXS_CONTEXT,
8992 &emlxs_attach_debug_msg,
8993 "Cfg error: Invalid rpwd type found. type=%x",
8994 auth_key->remote_password_type);
8995
8996 errors++;
8997 goto out;
8998 }
8999 auth_key->remote_password_length = (uint16_t)j;
9000
9001 if (errors) {
9002 goto out;
9003 }
9004 /* Verify values */
9005 if (auth_key->local_password_type == 0 ||
9006 auth_key->local_password_type > 3 ||
9007 auth_key->local_password_length == 0) {
9008
9009 auth_key->local_password_type = 3;
9010 auth_key->local_password_length = 0;
9011 bzero(auth_key->local_password,
9012 sizeof (auth_key->local_password));
9013 }
9014 if (auth_key->remote_password_type == 0 ||
9015 auth_key->remote_password_type > 3 ||
9016 auth_key->remote_password_length == 0) {
9017
9018 auth_key->remote_password_type = 3;
9019 auth_key->remote_password_length = 0;
9020 bzero(auth_key->remote_password,
9021 sizeof (auth_key->remote_password));
9022 }
9023 /* Display entry */
9024 emlxs_auth_key_print(hba, auth_key);
9025
9026 out:
9027 if (errors) {
9028 bzero(auth_key, sizeof (emlxs_auth_key_t));
9029 return (0);
9030 }
9031 return (1);
9032
9033 } /* emlxs_auth_key_parse() */
9034
9035
9036 /* ************************** AUTH DFCLIB SUPPORT *********************** */
9037
9038 /* Provides DFC support for emlxs_dfc_init_auth() */
9039 extern uint32_t
emlxs_dhc_init_auth(emlxs_hba_t * hba,uint8_t * lwwpn,uint8_t * rwwpn)9040 emlxs_dhc_init_auth(emlxs_hba_t *hba, uint8_t *lwwpn, uint8_t *rwwpn)
9041 {
9042 emlxs_port_t *port = &PPORT;
9043 emlxs_config_t *cfg = &CFG;
9044 NODELIST *ndlp;
9045 uint32_t vpi;
9046 char s_wwpn[64];
9047
9048 /* Return is authentication is not enabled */
9049 if (cfg[CFG_AUTH_ENABLE].current == 0) {
9050 EMLXS_MSGF(EMLXS_CONTEXT,
9051 &emlxs_fcsp_debug_msg,
9052 "dhc_init_auth. Auth disabled.");
9053
9054 return (DFC_AUTH_AUTHENTICATION_DISABLED);
9055 }
9056 /* Scan for lwwpn match */
9057 for (vpi = 0; vpi < MAX_VPORTS; vpi++) {
9058 port = &VPORT(vpi);
9059
9060 if (!(port->flag & EMLXS_PORT_BOUND)) {
9061 continue;
9062 }
9063 if (bcmp((uint8_t *)&port->wwpn, lwwpn, 8) == 0) {
9064 break;
9065 }
9066 }
9067
9068 if (vpi == MAX_VPORTS) {
9069 EMLXS_MSGF(EMLXS_CONTEXT,
9070 &emlxs_dfc_error_msg,
9071 "dhc_init_auth: lwwpn not found. %s",
9072 emlxs_wwn_xlate(s_wwpn, sizeof (s_wwpn), lwwpn));
9073
9074 return (DFC_AUTH_WWN_NOT_FOUND);
9075 }
9076 if (bcmp(rwwpn, emlxs_fabric_wwn, 8) == 0) {
9077 /* Scan for fabric node */
9078 if ((ndlp = emlxs_node_find_did(port, FABRIC_DID, 1)) == NULL) {
9079 EMLXS_MSGF(EMLXS_CONTEXT,
9080 &emlxs_dfc_error_msg,
9081 "dhc_init_auth: fabric node not found.");
9082
9083 return (DFC_AUTH_WWN_NOT_FOUND);
9084 }
9085 } else {
9086 /* Scan for rwwpn match */
9087 if ((ndlp = emlxs_node_find_wwpn(port, rwwpn, 1)) == NULL) {
9088 EMLXS_MSGF(EMLXS_CONTEXT,
9089 &emlxs_dfc_error_msg,
9090 "dhc_init_auth: rwwpn not found. %s",
9091 emlxs_wwn_xlate(s_wwpn, sizeof (s_wwpn), rwwpn));
9092
9093 return (DFC_AUTH_WWN_NOT_FOUND);
9094 }
9095 }
9096
9097 if ((ndlp->nlp_DID != FABRIC_DID) &&
9098 ((port->port_dhc.state != ELX_FABRIC_AUTH_SUCCESS))) {
9099 return (DFC_IO_ERROR);
9100 }
9101 if (ndlp->node_dhc.state >= NODE_STATE_AUTH_NEGOTIATE_ISSUE) {
9102 return (DFC_AUTH_AUTHENTICATION_GOINGON);
9103 }
9104 if (ndlp->node_dhc.state == NODE_STATE_AUTH_SUCCESS) {
9105 ndlp->node_dhc.nlp_reauth_status = NLP_HOST_REAUTH_IN_PROGRESS;
9106 }
9107 /* Attempt to start authentication */
9108 if (emlxs_dhc_auth_start(port, ndlp, NULL, NULL) != 0) {
9109 return (DFC_IO_ERROR);
9110 }
9111 return (0);
9112
9113 } /* emlxs_dhc_init_auth() */
9114
9115
9116 /* Provides DFC support for emlxs_dfc_get_auth_cfg() */
9117 extern uint32_t
emlxs_dhc_get_auth_cfg(emlxs_hba_t * hba,dfc_fcsp_config_t * fcsp_cfg)9118 emlxs_dhc_get_auth_cfg(emlxs_hba_t *hba, dfc_fcsp_config_t *fcsp_cfg)
9119 {
9120 emlxs_port_t *port = &PPORT;
9121 emlxs_config_t *cfg = &CFG;
9122 char s_lwwpn[64];
9123 char s_rwwpn[64];
9124 emlxs_auth_cfg_t *auth_cfg;
9125 uint32_t i;
9126
9127 /* Return is authentication is not enabled */
9128 if (cfg[CFG_AUTH_ENABLE].current == 0) {
9129 EMLXS_MSGF(EMLXS_CONTEXT,
9130 &emlxs_fcsp_debug_msg,
9131 "dhc_get_auth_cfg. Auth disabled.");
9132
9133 return (DFC_AUTH_AUTHENTICATION_DISABLED);
9134 }
9135 mutex_enter(&hba->auth_lock);
9136
9137 auth_cfg = emlxs_auth_cfg_get(hba,
9138 (uint8_t *)&fcsp_cfg->lwwpn, (uint8_t *)&fcsp_cfg->rwwpn);
9139
9140 if (!auth_cfg) {
9141 EMLXS_MSGF(EMLXS_CONTEXT,
9142 &emlxs_dfc_error_msg,
9143 "dhc_get_auth_cfg: entry not found. %s:%s",
9144 emlxs_wwn_xlate(s_lwwpn, sizeof (s_lwwpn),
9145 (uint8_t *)&fcsp_cfg->lwwpn),
9146 emlxs_wwn_xlate(s_rwwpn, sizeof (s_rwwpn),
9147 (uint8_t *)&fcsp_cfg->rwwpn));
9148
9149 mutex_exit(&hba->auth_lock);
9150
9151 return (DFC_AUTH_NOT_CONFIGURED);
9152 }
9153 fcsp_cfg->auth_tov = auth_cfg->authentication_timeout;
9154 fcsp_cfg->auth_mode = auth_cfg->authentication_mode;
9155 fcsp_cfg->auth_bidir = auth_cfg->bidirectional;
9156
9157 for (i = 0; i < 4; i++) {
9158 fcsp_cfg->type_priority[i] =
9159 auth_cfg->authentication_type_priority[i];
9160 fcsp_cfg->hash_priority[i] =
9161 auth_cfg->hash_priority[i];
9162 }
9163
9164 for (i = 0; i < 8; i++) {
9165 fcsp_cfg->group_priority[i] = auth_cfg->dh_group_priority[i];
9166 }
9167
9168 fcsp_cfg->reauth_tov = auth_cfg->reauthenticate_time_interval;
9169
9170 mutex_exit(&hba->auth_lock);
9171
9172 return (0);
9173
9174 } /* emlxs_dhc_get_auth_cfg() */
9175
9176
9177 /* Provides DFC support for emlxs_dfc_set_auth_cfg() */
9178 extern uint32_t
emlxs_dhc_add_auth_cfg(emlxs_hba_t * hba,dfc_fcsp_config_t * fcsp_cfg,dfc_password_t * dfc_pwd)9179 emlxs_dhc_add_auth_cfg(
9180 emlxs_hba_t *hba,
9181 dfc_fcsp_config_t *fcsp_cfg,
9182 dfc_password_t *dfc_pwd)
9183 {
9184 emlxs_port_t *port = &PPORT;
9185 emlxs_config_t *cfg = &CFG;
9186 emlxs_auth_cfg_t *auth_cfg;
9187 emlxs_auth_key_t *auth_key;
9188 uint32_t i;
9189 NODELIST *ndlp;
9190
9191 /* Return if authentication is not enabled */
9192 if (cfg[CFG_AUTH_ENABLE].current == 0) {
9193 EMLXS_MSGF(EMLXS_CONTEXT,
9194 &emlxs_fcsp_debug_msg,
9195 "dhc_add_auth_cfg. Auth disabled.");
9196
9197 return (DFC_AUTH_AUTHENTICATION_DISABLED);
9198 }
9199 mutex_enter(&hba->auth_lock);
9200
9201 auth_key = emlxs_auth_key_get(hba,
9202 (uint8_t *)&fcsp_cfg->lwwpn, (uint8_t *)&fcsp_cfg->rwwpn);
9203
9204 if (auth_key &&
9205 (auth_key->local_password_type == PASSWORD_TYPE_ASCII ||
9206 auth_key->local_password_type == PASSWORD_TYPE_BINARY)) {
9207
9208 /* Verify local password */
9209 if ((auth_key->local_password_length != dfc_pwd->length) ||
9210 (auth_key->local_password_type != dfc_pwd->type) ||
9211 bcmp(dfc_pwd->password, auth_key->local_password,
9212 dfc_pwd->length)) {
9213 EMLXS_MSGF(EMLXS_CONTEXT,
9214 &emlxs_dfc_error_msg,
9215 "dhc_add_auth_cfg: Invalid local password.");
9216
9217 mutex_exit(&hba->auth_lock);
9218
9219 return (DFC_AUTH_COMPARE_FAILED);
9220 }
9221 }
9222 /* Create entry */
9223 auth_cfg = emlxs_auth_cfg_create(hba,
9224 (uint8_t *)&fcsp_cfg->lwwpn,
9225 (uint8_t *)&fcsp_cfg->rwwpn);
9226
9227 if (!auth_cfg) {
9228 EMLXS_MSGF(EMLXS_CONTEXT,
9229 &emlxs_dfc_error_msg,
9230 "dhc_add_auth_cfg: Out of memory.");
9231
9232 mutex_exit(&hba->auth_lock);
9233
9234 return (DFC_SYSRES_ERROR);
9235 }
9236 /* Init entry */
9237 auth_cfg->authentication_timeout = fcsp_cfg->auth_tov;
9238 auth_cfg->authentication_mode = fcsp_cfg->auth_mode;
9239 auth_cfg->bidirectional = fcsp_cfg->auth_bidir;
9240
9241 for (i = 0; i < 4; i++) {
9242 auth_cfg->authentication_type_priority[i] =
9243 fcsp_cfg->type_priority[i];
9244 auth_cfg->hash_priority[i] =
9245 fcsp_cfg->hash_priority[i];
9246 }
9247
9248 for (i = 0; i < 8; i++) {
9249 auth_cfg->dh_group_priority[i] = fcsp_cfg->group_priority[i];
9250 }
9251
9252 auth_cfg->reauthenticate_time_interval = fcsp_cfg->reauth_tov;
9253
9254 emlxs_auth_cfg_print(hba, auth_cfg);
9255
9256 /* Cancel old reauth to restart the new one if necessary */
9257
9258 /* Scan for lwwpn match */
9259 for (i = 0; i < MAX_VPORTS; i++) {
9260 port = &VPORT(i);
9261
9262 if (!(port->flag & EMLXS_PORT_BOUND)) {
9263 continue;
9264 }
9265 if (bcmp((uint8_t *)&fcsp_cfg->lwwpn,
9266 (uint8_t *)&port->wwpn, 8)) {
9267 continue;
9268 }
9269 /* Port match found */
9270
9271 if (bcmp((uint8_t *)&fcsp_cfg->rwwpn,
9272 emlxs_fabric_wwn, 8) == 0) {
9273 /* Scan for fabric node */
9274 if ((ndlp = emlxs_node_find_did(port,
9275 FABRIC_DID, 1)) == NULL) {
9276 break;
9277 }
9278 } else {
9279 /* Scan for rwwpn match */
9280 if ((ndlp = emlxs_node_find_wwpn(port,
9281 (uint8_t *)&fcsp_cfg->rwwpn, 1)) == NULL) {
9282 break;
9283 }
9284 }
9285
9286 emlxs_dhc_set_reauth_time(port, ndlp, ENABLE);
9287
9288 break;
9289 }
9290
9291 mutex_exit(&hba->auth_lock);
9292
9293 return (0);
9294
9295 } /* emlxs_dhc_add_auth_cfg() */
9296
9297
9298 /* Provides DFC support for emlxs_dfc_set_auth_cfg() */
9299 extern uint32_t
emlxs_dhc_delete_auth_cfg(emlxs_hba_t * hba,dfc_fcsp_config_t * fcsp_cfg,dfc_password_t * dfc_pwd)9300 emlxs_dhc_delete_auth_cfg(
9301 emlxs_hba_t *hba,
9302 dfc_fcsp_config_t *fcsp_cfg,
9303 dfc_password_t *dfc_pwd)
9304 {
9305 emlxs_port_t *port = &PPORT;
9306 emlxs_config_t *cfg = &CFG;
9307 char s_lwwpn[64];
9308 char s_rwwpn[64];
9309 emlxs_auth_key_t *auth_key;
9310 emlxs_auth_cfg_t *auth_cfg;
9311
9312 /* Return is authentication is not enabled */
9313 if (cfg[CFG_AUTH_ENABLE].current == 0) {
9314 EMLXS_MSGF(EMLXS_CONTEXT,
9315 &emlxs_fcsp_debug_msg,
9316 "dhc_delete_auth_cfg. Auth disabled.");
9317
9318 return (DFC_AUTH_AUTHENTICATION_DISABLED);
9319 }
9320 mutex_enter(&hba->auth_lock);
9321
9322 auth_key = emlxs_auth_key_get(hba,
9323 (uint8_t *)&fcsp_cfg->lwwpn,
9324 (uint8_t *)&fcsp_cfg->rwwpn);
9325
9326 if (auth_key &&
9327 (auth_key->local_password_type == PASSWORD_TYPE_ASCII ||
9328 auth_key->local_password_type ==
9329 PASSWORD_TYPE_BINARY)) {
9330 /* Verify local password */
9331 if ((auth_key->local_password_length != dfc_pwd->length) ||
9332 (auth_key->local_password_type != dfc_pwd->type) ||
9333 bcmp(dfc_pwd->password,
9334 auth_key->local_password,
9335 dfc_pwd->length)) {
9336
9337 EMLXS_MSGF(EMLXS_CONTEXT,
9338 &emlxs_dfc_error_msg,
9339 "dhc_delete_auth_cfg: Ivld local pwd.");
9340
9341 mutex_exit(&hba->auth_lock);
9342
9343 return (DFC_AUTH_COMPARE_FAILED);
9344 }
9345 }
9346 auth_cfg = emlxs_auth_cfg_get(hba,
9347 (uint8_t *)&fcsp_cfg->lwwpn, (uint8_t *)&fcsp_cfg->rwwpn);
9348
9349 if (!auth_cfg) {
9350 EMLXS_MSGF(EMLXS_CONTEXT,
9351 &emlxs_dfc_error_msg,
9352 "dhc_delete_auth_cfg: entry not found. %s:%s",
9353 emlxs_wwn_xlate(s_lwwpn, sizeof (s_lwwpn),
9354 (uint8_t *)&fcsp_cfg->lwwpn),
9355 emlxs_wwn_xlate(s_rwwpn, sizeof (s_rwwpn),
9356 (uint8_t *)&fcsp_cfg->rwwpn));
9357
9358 mutex_exit(&hba->auth_lock);
9359
9360 return (DFC_AUTH_WWN_NOT_FOUND);
9361 }
9362 /* Destroy cfg entry */
9363 emlxs_auth_cfg_destroy(hba, auth_cfg);
9364
9365 /* Destroy pwd entry */
9366 emlxs_auth_key_destroy(hba, auth_key);
9367
9368 mutex_exit(&hba->auth_lock);
9369
9370 return (0);
9371
9372 } /* emlxs_dhc_delete_auth_cfg() */
9373
9374
9375 /* Provides DFC support for emlxs_dfc_get_auth_key() */
9376 extern uint32_t
emlxs_dhc_get_auth_key(emlxs_hba_t * hba,dfc_auth_password_t * dfc_auth_pwd)9377 emlxs_dhc_get_auth_key(emlxs_hba_t *hba, dfc_auth_password_t *dfc_auth_pwd)
9378 {
9379 emlxs_port_t *port = &PPORT;
9380 emlxs_config_t *cfg = &CFG;
9381 char s_lwwpn[64];
9382 char s_rwwpn[64];
9383 emlxs_auth_key_t *auth_key;
9384
9385 /* Return is authentication is not enabled */
9386 if (cfg[CFG_AUTH_ENABLE].current == 0) {
9387 EMLXS_MSGF(EMLXS_CONTEXT,
9388 &emlxs_fcsp_debug_msg,
9389 "dhc_get_auth_key. Auth disabled.");
9390
9391 return (DFC_AUTH_AUTHENTICATION_DISABLED);
9392 }
9393 mutex_enter(&hba->auth_lock);
9394
9395 auth_key = emlxs_auth_key_get(hba,
9396 (uint8_t *)&dfc_auth_pwd->lwwpn,
9397 (uint8_t *)&dfc_auth_pwd->rwwpn);
9398
9399 if (!auth_key) {
9400 EMLXS_MSGF(EMLXS_CONTEXT,
9401 &emlxs_dfc_error_msg,
9402 "dhc_get_auth_key: entry not found. %s:%s",
9403 emlxs_wwn_xlate(s_lwwpn, sizeof (s_lwwpn),
9404 (uint8_t *)&dfc_auth_pwd->lwwpn),
9405 emlxs_wwn_xlate(s_rwwpn, sizeof (s_rwwpn),
9406 (uint8_t *)&dfc_auth_pwd->rwwpn));
9407
9408 mutex_exit(&hba->auth_lock);
9409
9410 return (DFC_AUTH_NOT_CONFIGURED);
9411 }
9412 dfc_auth_pwd->lpw.length = auth_key->local_password_length;
9413 dfc_auth_pwd->lpw.type = auth_key->local_password_type;
9414 /*
9415 * bcopy(auth_key->local_password, dfc_auth_pwd->lpw.password,
9416 * dfc_auth_pwd->lpw.length);
9417 */
9418
9419 dfc_auth_pwd->rpw.length = auth_key->remote_password_length;
9420 dfc_auth_pwd->rpw.type = auth_key->remote_password_type;
9421 /*
9422 * bcopy(auth_key->remote_password, dfc_auth_pwd->rpw.password,
9423 * dfc_auth_pwd->rpw.length);
9424 */
9425
9426 dfc_auth_pwd->lpw_new.length = auth_key->local_password_length;
9427 dfc_auth_pwd->lpw_new.type = auth_key->local_password_type;
9428 /*
9429 * bcopy(auth_key->local_password, dfc_auth_pwd->lpw_new.password,
9430 * dfc_auth_pwd->lpw_new.length);
9431 */
9432
9433 dfc_auth_pwd->rpw_new.length = auth_key->remote_password_length;
9434 dfc_auth_pwd->rpw_new.type = auth_key->remote_password_type;
9435 /*
9436 * bcopy(auth_key->remote_password, dfc_auth_pwd->rpw_new.password,
9437 * dfc_auth_pwd->rpw_new.length);
9438 */
9439
9440 mutex_exit(&hba->auth_lock);
9441
9442 return (0);
9443
9444 } /* emlxs_dhc_get_auth_key() */
9445
9446
9447 /* Provides DFC support for emlxs_dfc_set_auth_key() */
9448 extern uint32_t
emlxs_dhc_set_auth_key(emlxs_hba_t * hba,dfc_auth_password_t * dfc_pwd)9449 emlxs_dhc_set_auth_key(emlxs_hba_t *hba, dfc_auth_password_t *dfc_pwd)
9450 {
9451 emlxs_port_t *port = &PPORT;
9452 emlxs_config_t *cfg = &CFG;
9453 emlxs_auth_key_t *auth_key;
9454 uint32_t length;
9455
9456 /* Return is authentication is not enabled */
9457 if (cfg[CFG_AUTH_ENABLE].current == 0) {
9458 EMLXS_MSGF(EMLXS_CONTEXT,
9459 &emlxs_fcsp_debug_msg,
9460 "dhc_set_auth_key. Auth disabled.");
9461
9462 return (DFC_AUTH_AUTHENTICATION_DISABLED);
9463 }
9464
9465 /* Check to make sure localpwd does not equal to remotepwd */
9466 /* if they are given in the same time, if not, see below */
9467 if ((dfc_pwd->lpw_new.type == PASSWORD_TYPE_ASCII ||
9468 dfc_pwd->lpw_new.type == PASSWORD_TYPE_BINARY) &&
9469 (dfc_pwd->rpw_new.type == PASSWORD_TYPE_ASCII ||
9470 dfc_pwd->rpw_new.type == PASSWORD_TYPE_BINARY)) {
9471 if (bcmp(dfc_pwd->lpw_new.password,
9472 dfc_pwd->rpw_new.password,
9473 dfc_pwd->lpw_new.length) == 0) {
9474 EMLXS_MSGF(EMLXS_CONTEXT,
9475 &emlxs_fcsp_debug_msg,
9476 "dhc_set_auth_key. nlpwd==nrpwd");
9477
9478 return (DFC_AUTH_LOCAL_REMOTE_PWD_EQUAL);
9479 }
9480 }
9481
9482 mutex_enter(&hba->auth_lock);
9483
9484 auth_key = emlxs_auth_key_get(hba,
9485 (uint8_t *)&dfc_pwd->lwwpn,
9486 (uint8_t *)&dfc_pwd->rwwpn);
9487
9488 /* If entry does not exist, then create entry */
9489 if (!auth_key) {
9490 auth_key = emlxs_auth_key_create(hba,
9491 (uint8_t *)&dfc_pwd->lwwpn,
9492 (uint8_t *)&dfc_pwd->rwwpn);
9493
9494 if (!auth_key) {
9495 EMLXS_MSGF(EMLXS_CONTEXT,
9496 &emlxs_dfc_error_msg,
9497 "dhc_set_auth_key: Out of memory.");
9498
9499 mutex_exit(&hba->auth_lock);
9500
9501 return (DFC_SYSRES_ERROR);
9502 }
9503 }
9504
9505 /* Check if a new local password is provided */
9506 if (dfc_pwd->lpw_new.type == PASSWORD_TYPE_ASCII ||
9507 dfc_pwd->lpw_new.type == PASSWORD_TYPE_BINARY) {
9508 /* Check if current password should be checked */
9509 if (auth_key->local_password_type == PASSWORD_TYPE_ASCII ||
9510 auth_key->local_password_type == PASSWORD_TYPE_BINARY) {
9511 /* Verify current local password */
9512 if ((auth_key->local_password_length !=
9513 dfc_pwd->lpw.length) ||
9514 (auth_key->local_password_type !=
9515 dfc_pwd->lpw.type) ||
9516 bcmp(dfc_pwd->lpw.password,
9517 auth_key->local_password,
9518 dfc_pwd->lpw.length)) {
9519 EMLXS_MSGF(EMLXS_CONTEXT,
9520 &emlxs_dfc_error_msg,
9521 "dhc_set_auth_key: Invalid local password.");
9522
9523 mutex_exit(&hba->auth_lock);
9524
9525 return (DFC_AUTH_COMPARE_FAILED);
9526 }
9527 }
9528
9529 /*
9530 * Make sure the new local pwd is not equal to the current
9531 * remote pwd if any
9532 */
9533 if (auth_key->remote_password_type == PASSWORD_TYPE_ASCII ||
9534 auth_key->remote_password_type == PASSWORD_TYPE_BINARY) {
9535 if ((auth_key->remote_password_length ==
9536 dfc_pwd->lpw_new.length) &&
9537 (bcmp(dfc_pwd->lpw_new.password,
9538 auth_key->remote_password,
9539 dfc_pwd->lpw_new.length) == 0)) {
9540 EMLXS_MSGF(EMLXS_CONTEXT,
9541 &emlxs_dfc_error_msg,
9542 "dhc_set_auth_key: nlpwd==crpwd");
9543
9544 mutex_exit(&hba->auth_lock);
9545
9546 return (DFC_AUTH_LOCAL_REMOTE_PWD_EQUAL);
9547 }
9548 }
9549 /* Update local entry */
9550 auth_key->local_password_length = dfc_pwd->lpw_new.length;
9551 auth_key->local_password_type = dfc_pwd->lpw_new.type;
9552 bzero(auth_key->local_password,
9553 sizeof (auth_key->local_password));
9554 length = min(dfc_pwd->lpw_new.length,
9555 sizeof (auth_key->local_password));
9556 bcopy(dfc_pwd->lpw_new.password,
9557 auth_key->local_password, length);
9558 }
9559 /* Check if a new remote password is provided */
9560 if (dfc_pwd->rpw_new.type == PASSWORD_TYPE_ASCII ||
9561 dfc_pwd->rpw_new.type == PASSWORD_TYPE_BINARY) {
9562 /* Check if current password should be checked */
9563 if (auth_key->remote_password_type == PASSWORD_TYPE_ASCII ||
9564 auth_key->remote_password_type == PASSWORD_TYPE_BINARY) {
9565 /* Verify current remote password */
9566 if ((auth_key->remote_password_length !=
9567 dfc_pwd->rpw.length) ||
9568 (auth_key->remote_password_type !=
9569 dfc_pwd->rpw.type) ||
9570 bcmp(dfc_pwd->rpw.password,
9571 auth_key->remote_password,
9572 dfc_pwd->rpw.length)) {
9573 EMLXS_MSGF(EMLXS_CONTEXT,
9574 &emlxs_dfc_error_msg,
9575 "dhc_set_auth_key: Invalid remote password.");
9576
9577 mutex_exit(&hba->auth_lock);
9578
9579 return (DFC_AUTH_COMPARE_FAILED);
9580 }
9581 }
9582
9583 /*
9584 * Make sure the new remote pwd is not equal to the current
9585 * local pwd if any
9586 */
9587 if (auth_key->local_password_type == PASSWORD_TYPE_ASCII ||
9588 auth_key->local_password_type == PASSWORD_TYPE_BINARY) {
9589 if ((auth_key->local_password_length ==
9590 dfc_pwd->rpw_new.length) &&
9591 (bcmp(dfc_pwd->rpw_new.password,
9592 auth_key->local_password,
9593 dfc_pwd->rpw_new.length) == 0)) {
9594 EMLXS_MSGF(EMLXS_CONTEXT,
9595 &emlxs_dfc_error_msg,
9596 "dhc_set_auth_key: nrpwd==clpwd");
9597
9598 mutex_exit(&hba->auth_lock);
9599
9600 return (DFC_AUTH_LOCAL_REMOTE_PWD_EQUAL);
9601 }
9602 }
9603 /* Update remote entry */
9604 auth_key->remote_password_length = dfc_pwd->rpw_new.length;
9605 auth_key->remote_password_type = dfc_pwd->rpw_new.type;
9606 bzero(auth_key->remote_password,
9607 sizeof (auth_key->remote_password));
9608 length = min(dfc_pwd->rpw_new.length, 128);
9609 bcopy(dfc_pwd->rpw_new.password,
9610 auth_key->remote_password, length);
9611 }
9612 /* Update dfc local entry */
9613 dfc_pwd->lpw.length = auth_key->local_password_length;
9614 dfc_pwd->lpw.type = auth_key->local_password_type;
9615 bzero(dfc_pwd->lpw.password, sizeof (dfc_pwd->lpw.password));
9616 length = min(auth_key->local_password_length,
9617 sizeof (dfc_pwd->lpw.password));
9618 bcopy(auth_key->local_password, dfc_pwd->lpw.password, length);
9619
9620 /* Update dfc remote entry */
9621 dfc_pwd->rpw.length = auth_key->remote_password_length;
9622 dfc_pwd->rpw.type = auth_key->remote_password_type;
9623 bzero(dfc_pwd->rpw.password, sizeof (dfc_pwd->rpw.password));
9624 length = min(auth_key->remote_password_length,
9625 sizeof (dfc_pwd->rpw.password));
9626 bcopy(auth_key->remote_password, dfc_pwd->rpw.password, length);
9627
9628 emlxs_auth_key_print(hba, auth_key);
9629
9630 mutex_exit(&hba->auth_lock);
9631
9632 return (0);
9633
9634 } /* emlxs_dhc_set_auth_key() */
9635
9636
9637 /* Provides DFC support for emlxs_dfc_get_auth_status() */
9638 extern uint32_t
emlxs_dhc_get_auth_status(emlxs_hba_t * hba,dfc_auth_status_t * fcsp_status)9639 emlxs_dhc_get_auth_status(emlxs_hba_t *hba, dfc_auth_status_t *fcsp_status)
9640 {
9641 emlxs_port_t *port = &PPORT;
9642 emlxs_config_t *cfg = &CFG;
9643 char s_lwwpn[64];
9644 char s_rwwpn[64];
9645 emlxs_auth_cfg_t *auth_cfg;
9646 dfc_auth_status_t *auth_status;
9647 NODELIST *ndlp;
9648 uint32_t rc;
9649 time_t auth_time;
9650 uint32_t update;
9651
9652 /* Return is authentication is not enabled */
9653 if (cfg[CFG_AUTH_ENABLE].current == 0) {
9654 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_debug_msg,
9655 "dhc_get_auth_status. Auth disabled.");
9656
9657 return (DFC_AUTH_AUTHENTICATION_DISABLED);
9658 }
9659 mutex_enter(&hba->auth_lock);
9660
9661 auth_cfg = emlxs_auth_cfg_get(hba, (uint8_t *)&fcsp_status->lwwpn,
9662 (uint8_t *)&fcsp_status->rwwpn);
9663
9664 if (!auth_cfg) {
9665 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9666 "dhc_get_auth_status: entry not found. %s:%s",
9667 emlxs_wwn_xlate(s_lwwpn, sizeof (s_lwwpn),
9668 (uint8_t *)&fcsp_status->lwwpn),
9669 emlxs_wwn_xlate(s_rwwpn, sizeof (s_rwwpn),
9670 (uint8_t *)&fcsp_status->rwwpn));
9671
9672 mutex_exit(&hba->auth_lock);
9673
9674 return (DFC_AUTH_NOT_CONFIGURED);
9675 }
9676 if (bcmp((uint8_t *)&fcsp_status->rwwpn,
9677 (uint8_t *)emlxs_fabric_wwn, 8) == 0) {
9678 auth_status = &port->port_dhc.auth_status;
9679 auth_time = port->port_dhc.auth_time;
9680 ndlp = emlxs_node_find_did(port, FABRIC_DID, 1);
9681 } else {
9682 auth_status = &auth_cfg->auth_status;
9683 auth_time = auth_cfg->auth_time;
9684 ndlp = auth_cfg->node;
9685 }
9686
9687 update = 0;
9688
9689 /* Check if node is still available */
9690 if (ndlp && ndlp->nlp_active) {
9691 emlxs_dhc_status(port, ndlp, 0, 0);
9692 update = 1;
9693 } else {
9694 rc = DFC_AUTH_WWN_NOT_FOUND;
9695 }
9696
9697
9698 if (update) {
9699 fcsp_status->auth_state = auth_status->auth_state;
9700 fcsp_status->auth_failReason = auth_status->auth_failReason;
9701 fcsp_status->type_priority = auth_status->type_priority;
9702 fcsp_status->group_priority = auth_status->group_priority;
9703 fcsp_status->hash_priority = auth_status->hash_priority;
9704 fcsp_status->localAuth = auth_status->localAuth;
9705 fcsp_status->remoteAuth = auth_status->remoteAuth;
9706 fcsp_status->time_from_last_auth = DRV_TIME - auth_time;
9707 fcsp_status->time_until_next_auth =
9708 auth_status->time_until_next_auth;
9709
9710 rc = 0;
9711 } else {
9712 rc = DFC_AUTH_WWN_NOT_FOUND;
9713 }
9714
9715 mutex_exit(&hba->auth_lock);
9716
9717 return (rc);
9718
9719 } /* emlxs_dhc_get_auth_status() */
9720
9721
9722 /* Provides DFC support for emlxs_dfc_get_auth_list() */
9723 /* auth_lock must be held when calling. */
9724 /* fcsp_cfg must be large enough to hold hba->auth_cfg_count entries */
9725 extern uint32_t
emlxs_dhc_get_auth_cfg_table(emlxs_hba_t * hba,dfc_fcsp_config_t * fcsp_cfg)9726 emlxs_dhc_get_auth_cfg_table(emlxs_hba_t *hba, dfc_fcsp_config_t *fcsp_cfg)
9727 {
9728 emlxs_port_t *port = &PPORT;
9729 emlxs_config_t *cfg = &CFG;
9730 emlxs_auth_cfg_t *auth_cfg;
9731 uint32_t i;
9732
9733 /* Return if authentication is not enabled */
9734 if (cfg[CFG_AUTH_ENABLE].current == 0) {
9735 EMLXS_MSGF(EMLXS_CONTEXT,
9736 &emlxs_fcsp_debug_msg,
9737 "dhc_get_auth_cfg_table. Auth disabled.");
9738
9739 return (DFC_AUTH_AUTHENTICATION_DISABLED);
9740 }
9741 for (auth_cfg = hba->auth_cfg.next;
9742 auth_cfg != &hba->auth_cfg;
9743 auth_cfg = auth_cfg->next) {
9744 bcopy((uint8_t *)&auth_cfg->local_entity,
9745 (uint8_t *)&fcsp_cfg->lwwpn, 8);
9746 bcopy((uint8_t *)&auth_cfg->remote_entity,
9747 (uint8_t *)&fcsp_cfg->rwwpn, 8);
9748
9749 fcsp_cfg->auth_tov = auth_cfg->authentication_timeout;
9750 fcsp_cfg->auth_mode = auth_cfg->authentication_mode;
9751 fcsp_cfg->auth_bidir = auth_cfg->bidirectional;
9752
9753 for (i = 0; i < 4; i++) {
9754 fcsp_cfg->type_priority[i] =
9755 auth_cfg->authentication_type_priority[i];
9756 fcsp_cfg->hash_priority[i] =
9757 auth_cfg->hash_priority[i];
9758 }
9759
9760 for (i = 0; i < 8; i++) {
9761 fcsp_cfg->group_priority[i] =
9762 auth_cfg->dh_group_priority[i];
9763 }
9764
9765 fcsp_cfg->reauth_tov = auth_cfg->reauthenticate_time_interval;
9766
9767 fcsp_cfg++;
9768 }
9769
9770 return (0);
9771
9772 } /* emlxs_dhc_get_auth_cfg_table() */
9773
9774
9775
9776 /* Provides DFC support for emlxs_dfc_get_auth_list() */
9777 /* auth_lock must be held when calling. */
9778 /* auth_pwd must be large enough to hold hba->auth_key_count entries */
9779 extern uint32_t
emlxs_dhc_get_auth_key_table(emlxs_hba_t * hba,dfc_auth_password_t * auth_pwd)9780 emlxs_dhc_get_auth_key_table(emlxs_hba_t *hba, dfc_auth_password_t *auth_pwd)
9781 {
9782 emlxs_port_t *port = &PPORT;
9783 emlxs_config_t *cfg = &CFG;
9784 emlxs_auth_key_t *auth_key;
9785
9786 /* Return if authentication is not enabled */
9787 if (cfg[CFG_AUTH_ENABLE].current == 0) {
9788 EMLXS_MSGF(EMLXS_CONTEXT,
9789 &emlxs_fcsp_debug_msg,
9790 "dhc_get_auth_key_table. Auth disabled.");
9791
9792 return (DFC_AUTH_AUTHENTICATION_DISABLED);
9793 }
9794 for (auth_key = hba->auth_key.next;
9795 auth_key != &hba->auth_key;
9796 auth_key = auth_key->next) {
9797 bcopy((uint8_t *)&auth_key->local_entity,
9798 (uint8_t *)&auth_pwd->lwwpn, 8);
9799 bcopy((uint8_t *)&auth_key->remote_entity,
9800 (uint8_t *)&auth_pwd->rwwpn, 8);
9801
9802 auth_pwd->lpw.length = auth_key->local_password_length;
9803 auth_pwd->lpw.type = auth_key->local_password_type;
9804 /*
9805 * bcopy(auth_key->local_password, auth_pwd->lpw.password,
9806 * auth_pwd->lpw.length);
9807 */
9808
9809 auth_pwd->rpw.length = auth_key->remote_password_length;
9810 auth_pwd->rpw.type = auth_key->remote_password_type;
9811 /*
9812 * bcopy(auth_key->remote_password, auth_pwd->rpw.password,
9813 * auth_pwd->rpw.length);
9814 */
9815
9816 auth_pwd->lpw_new.length = auth_key->local_password_length;
9817 auth_pwd->lpw_new.type = auth_key->local_password_type;
9818 /*
9819 * bcopy(auth_key->local_password,
9820 * auth_pwd->lpw_new.password, auth_pwd->lpw_new.length);
9821 */
9822
9823 auth_pwd->rpw_new.length = auth_key->remote_password_length;
9824 auth_pwd->rpw_new.type = auth_key->remote_password_type;
9825 /*
9826 * bcopy(auth_key->remote_password,
9827 * auth_pwd->rpw_new.password, auth_pwd->rpw_new.length);
9828 */
9829
9830 auth_pwd++;
9831 }
9832
9833 return (0);
9834
9835 } /* emlxs_dhc_get_auth_key_table() */
9836
9837 #endif /* DHCHAP_SUPPORT */
9838