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