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