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