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