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