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