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