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