eapfast_phase2.c
来自「linux 下通过802.1认证的安装包」· C语言 代码 · 共 1,907 行 · 第 1/4 页
C
1,907 行
debug_hex_dump(DEBUG_AUTHTYPES, phase2->sm->eapKeyData, 32);
if (phase2->simckj == NULL)
{
debug_printf(DEBUG_AUTHTYPES, "Generating a new S-IMCK[0].\n");
phase2->simckj = Malloc(40);
if (phase2->simckj == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't allocate memory to store "
"S-IMCK[0]!\n");
return NULL;
}
memcpy(phase2->simckj, phase2->pkeys->session_key_seed, 40);
}
key = Malloc(32);
if (key == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't allocate memory to store "
"temporary key data!\n");
return NULL;
}
memset(key, 0x00, 32);
if (phase2->sm->eapKeyData != NULL)
{
memcpy(key, phase2->sm->eapKeyData, 32);
}
keyblock = eapfast_phase2_t_prf(phase2->simckj, 40,
FAST_IMCK_LABEL, key, 32, 60);
cmkj = Malloc(20);
if (cmkj == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't allocate memory to store CMK[j]!\n");
return NULL;
}
// Store the new S-IMCK[j]
memcpy(phase2->simckj, keyblock, 40);
memcpy(cmkj, keyblock+40, 20);
return cmkj;
}
/****************************************************************
*
* Process a crypto binding TLV, and verify that it is valid. If it
* isn't valid, then wipe out the result packet that we have been
* building, and replace it with a Result-Failure TLV, and an Error TLV
* that indicates the problem was with the crypto-binding.
*
****************************************************************/
int eapfast_phase2_check_crypto_binding(eap_type_data *eapdata,
uint8_t *indata, uint16_t insize)
{
struct eapfast_crypto_binding_tlv *binding, *maccheck;
struct tls_vars *mytls_vars;
struct eapfast_phase2 *phase2;
uint8_t *temp;
uint8_t mac[20], nonce[32];
int len;
uint8_t *cmkj;
if (!xsup_assert((eapdata != NULL), "eapdata != NULL", FALSE))
return 0;
if (!xsup_assert((indata != NULL), "indata != NULL", FALSE))
{
eap_type_common_fail(eapdata);
return 0;
}
if (!xsup_assert((insize >= sizeof(struct eapfast_crypto_binding_tlv)),
"insize is invalid", FALSE))
{
eap_type_common_fail(eapdata);
return 0;
}
mytls_vars = (struct tls_vars *)eapdata->eap_data;
phase2 = (struct eapfast_phase2 *)mytls_vars->phase2data;
binding = (struct eapfast_crypto_binding_tlv *)indata;
if ((ntohs(binding->length)+4) != sizeof(struct eapfast_crypto_binding_tlv))
{
debug_printf(DEBUG_NORMAL, "Crypto-Binding packet is a runt!\n");
eapfast_phase2_binding_failed(eapdata);
return 0;
}
binding = (struct eapfast_crypto_binding_tlv *)indata;
if (binding->version != FAST_CRYPTO_BIND_VERSION)
{
debug_printf(DEBUG_NORMAL, "Crypto-Binding version is invalid! "
"(Expected %d, got %d.)\n", FAST_CRYPTO_BIND_VERSION,
binding->version);
eapfast_phase2_binding_failed(eapdata);
return 0;
}
debug_printf(DEBUG_AUTHTYPES, "Crypto-Binding version is %d.\n",
binding->version);
if (binding->eap_version != eapfast_get_ver(eapdata))
{
debug_printf(DEBUG_NORMAL, "Crypto-Binding EAP version is invalid! "
"(Expected %d, got %d.)\n", eapfast_get_ver(eapdata),
binding->eap_version);
eapfast_phase2_binding_failed(eapdata);
return 0;
}
debug_printf(DEBUG_AUTHTYPES, "EAP Version is %d\n", binding->eap_version);
if (binding->subtype != FAST_BINDING_REQUEST)
{
debug_printf(DEBUG_NORMAL, "Crypto-Binding subtype is invalid! "
"(Expected %d, got %d.)\n", FAST_BINDING_REQUEST,
binding->subtype);
eapfast_phase2_binding_failed(eapdata);
return 0;
}
/*
if (phase2->sm->eapKeyAvailable != TRUE)
{
debug_printf(DEBUG_NORMAL, "No keying material available from phase 2! "
"(Unable to generate the Compound MAC.)\n");
eapfast_phase2_binding_failed(eapdata);
return 0;
}
*/
temp = Malloc(ntohs(binding->length)+4);
if (temp == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't allocate memory to store temporary"
" Crypto-Binding TLV data.\n");
eapfast_phase2_binding_failed(eapdata);
return 0;
}
if (!xsup_assert((phase2->sm != NULL), "phase2->sm != NULL", FALSE))
{
eapfast_phase2_binding_failed(eapdata);
FREE(temp);
return 0;
}
memcpy(temp, binding, (ntohs(binding->length)+4));
maccheck = (struct eapfast_crypto_binding_tlv *)temp;
// Zero out the MAC section.
memset(maccheck->compound_mac, 0x00, sizeof(maccheck->compound_mac));
debug_printf(DEBUG_AUTHTYPES, "Phase 2 Keying material (%d) : ",
phase2->sm->eapKeyLen);
debug_hex_printf(DEBUG_AUTHTYPES, phase2->sm->eapKeyData,
phase2->sm->eapKeyLen);
cmkj = eapfast_phase2_gen_cmkj(eapdata);
HMAC(EVP_sha1(), cmkj, 20, (unsigned char *)maccheck,
sizeof(struct eapfast_crypto_binding_tlv), (unsigned char *)&mac,
&len);
debug_printf(DEBUG_AUTHTYPES, "Calculated Compound MAC (%d)\t: ", len);
debug_hex_printf(DEBUG_AUTHTYPES, mac, len);
debug_printf(DEBUG_AUTHTYPES, "Expected Compound MAC \t: ");
debug_hex_printf(DEBUG_AUTHTYPES, binding->compound_mac,
sizeof(binding->compound_mac));
if (memcmp(mac, binding->compound_mac, sizeof(binding->compound_mac)) != 0)
{
debug_printf(DEBUG_NORMAL, "Compound MAC check failed!\n");
eapfast_phase2_binding_failed(eapdata);
FREE(temp);
return 0;
}
memcpy(nonce, binding->nonce, 32);
FREE(temp);
// The MAC check was a success. So, now we need to build the response
// CMAC, and send it along too.
temp = Malloc(sizeof(struct eapfast_crypto_binding_tlv));
if (temp == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't allocate memory to return the "
"crypto binding result.\n");
eapfast_phase2_binding_failed(eapdata);
return 0;
}
memset(temp, 0x00, sizeof(struct eapfast_crypto_binding_tlv));
binding = (struct eapfast_crypto_binding_tlv *)temp;
binding->type = htons(MANDATORY_TLV | FAST_CRYPTO_BINDING_TLV);
binding->length = htons(sizeof(struct eapfast_crypto_binding_tlv)-4);
binding->reserved = 0;
binding->version = FAST_CRYPTO_BIND_VERSION;
binding->eap_version = FAST_VERSION1;
binding->subtype = FAST_BINDING_RESPONSE;
memcpy(binding->nonce, nonce, 32);
binding->nonce[31]++;
HMAC(EVP_sha1(), cmkj, 20, temp, sizeof(struct eapfast_crypto_binding_tlv),
(unsigned char *)&mac, &len);
memcpy(binding->compound_mac, mac, 20);
memcpy(&phase2->result_data[phase2->result_size], temp,
sizeof(struct eapfast_crypto_binding_tlv));
phase2->result_size += sizeof(struct eapfast_crypto_binding_tlv);
return sizeof(struct eapfast_crypto_binding_tlv);
}
/*********************************************************************
*
* Process an ERROR TLV from the server. This code should validate
* the error from the server, and display some form of an error message
* to the user.
*
*********************************************************************/
uint16_t eapfast_phase2_process_error_tlv(uint8_t *indata)
{
struct eapfast_tlv_error *error;
if (!xsup_assert((indata != NULL), "indata != NULL", FALSE))
return 0;
error = (struct eapfast_tlv_error *)indata;
if (ntohs(error->length) != 4)
{
debug_printf(DEBUG_NORMAL, "The TLV length for the ERROR TLV was "
"invalid. Expected 4, got %d.\n", ntohs(error->length));
return ntohs(error->length)+4;
}
switch (ntohl(error->error_code))
{
case FAST_TUNNEL_COMPROMISE_ERROR:
debug_printf(DEBUG_NORMAL, "[EAP-FAST] Tunnel has been compromised!\n");
break;
case FAST_UNEXPECTED_TLVS_EXCHANGED:
debug_printf(DEBUG_NORMAL, "[EAP-FAST] Unexpected TLVs exchanged!\n");
break;
default:
debug_printf(DEBUG_NORMAL, "[EAP-FAST] Unknown error received. (Error "
"was %d.)\n", ntohl(error->error_code));
break;
}
return ntohs(error->length)+4;
}
/***************************************************************
*
* Process a phase 2 packet.
*
***************************************************************/
void eapfast_phase2_process(eap_type_data *eapdata, uint8_t *indata,
uint16_t insize)
{
struct eapfast_tlv *fastlv;
uint16_t value16;
struct tls_vars *mytls_vars;
struct eapfast_phase2 *phase2;
uint16_t consumed = 0, result = 0;
if (!xsup_assert((eapdata != NULL), "eapdata != NULL", FALSE))
return;
if (!xsup_assert((indata != NULL), "indata != NULL", FALSE))
{
eap_type_common_fail(eapdata);
return;
}
if (!xsup_assert((eapdata->eap_data != NULL), "eapdata->eap_data != NULL",
FALSE))
{
eap_type_common_fail(eapdata);
return;
}
mytls_vars = (struct tls_vars *)eapdata->eap_data;
if (!xsup_assert((mytls_vars->phase2data != NULL),
"mytls_vars->phase2data != NULL", FALSE))
{
eap_type_common_fail(eapdata);
return;
}
phase2 = (struct eapfast_phase2 *)mytls_vars->phase2data;
// Clear out our storage area, so that we can build the new response.
FREE(phase2->result_data);
phase2->result_size = 0;
phase2->result_data = Malloc(1600); // Should be plenty of space.
if (phase2->result_data == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't allocate memory to store response "
"data.\n");
eap_type_common_fail(eapdata);
return;
}
// Need to loop through all TLVs included, and make sure we process each one.
while (consumed < insize)
{
fastlv = (struct eapfast_tlv *)&indata[consumed];
value16 = ntohs(fastlv->type);
debug_printf(DEBUG_AUTHTYPES, "(Offset %d) PAC id (%d) : ", consumed,
(value16 & MANDATORY_TLV_MASK_OUT));
eapfast_phase2_PAC_id_to_str(DEBUG_AUTHTYPES,
(value16 & MANDATORY_TLV_MASK_OUT));
debug_printf_nl(DEBUG_AUTHTYPES, "\n");
switch (value16 & MANDATORY_TLV_MASK_OUT)
{
case FAST_RESULT_TLV:
result = eapfast_phase2_process_result_tlv(eapdata,
&indata[consumed],
(insize - consumed));
break;
case FAST_NAK_TLV:
// It is possible that the supplicant *COULD* get a NAK TLV, but
// that should require that we are attempting to use a TLV that
// may not be supported by the server. Since this implementation
// doesn't support anything like that, we should never get a
// NAK! If such code is ever added, we need to implement something
// here.
debug_printf(DEBUG_NORMAL, "Got a TLV NAK. This shouldn't happen!"
"\n");
result = 0;
break;
case FAST_ERROR_TLV:
debug_printf(DEBUG_NORMAL, "Got an ERROR TLV.\n");
result = eapfast_phase2_process_error_tlv(&indata[consumed]);
break;
case FAST_VENDOR_SPECIFIC_TLV:
debug_printf(DEBUG_NORMAL, "Vendor specific TLV found, but not "
"supported. NAKing.\n");
result = eapfast_phase2_vendor_tlv_nak(eapdata, &indata[consumed]);
break;
case FAST_EAP_PAYLOAD_TLV:
result = eapfast_phase2_eap_process(eapdata, &indata[consumed],
(insize - consumed));
break;
case FAST_INTERMEDIATE_RESULT_TLV:
result = eapfast_phase2_intermediate_result_process(eapdata,
&indata[consumed],
(insize - consumed));
break;
case FAST_PAC_TLV:
result = eapfast_phase2_pac_process(eapdata, &indata[consumed],
(insize - consumed));
break;
case FAST_CRYPTO_BINDING_TLV:
result = eapfast_phase2_check_crypto_binding(eapdata,
&indata[consumed],
(insize - consumed));
break;
case FAST_SERVER_TRUSTED_ROOT_TLV:
debug_printf(DEBUG_NORMAL, "Got a 'Server trusted root' TLV, but "
"this is not implemented, and should not happen!\n");
result = eapfast_phase2_tlv_nak(eapdata, &indata[consumed],
0x00000000,
FAST_SERVER_TRUSTED_ROOT_TLV);
break;
case FAST_REQUEST_ACTION_TLV:
debug_printf(DEBUG_NORMAL, "The server sent us a request for "
"action TLV. But, we should NEVER get one! NAKing"
"!\n");
result = eapfast_phase2_tlv_nak(eapdata, &indata[consumed],
0x00000000, FAST_REQUEST_ACTION_TLV);
break;
case FAST_PKCS7_TLV:
debug_printf(DEBUG_NORMAL, "Use of a PKCS#7 certificate is not "
"currently supported!\n");
result = eapfast_phase2_tlv_nak(eapdata, &indata[consumed],
0x00000000, FAST_PKCS7_TLV);
break;
default:
debug_printf(DEBUG_NORMAL, "Unknown TLV type %d.\n",
ntohs(fastlv->type));
result = eapfast_phase2_tlv_nak(eapdata, &indata[consumed],
0x00000000, ntohs(fastlv->type));
break;
}
if (result == 0)
{
// ACK! We couldn't process something for some reason. (The reason
// should have been displayed by the called function.)
return;
}
consumed += result;
}
}
/**********************************************************************
*
* Build an EAP-FAST response.
*
**********************************************************************/
void eapfast_phase2_buildResp(eap_type_data *eapdata, uint8_t *result,
uint16_t *result_size)
{
struct tls_vars *mytls_vars;
struct eapfast_phase2 *phase2;
if (!xsup_assert((eapdata != NULL), "eapdata != NULL", FALSE))
{
*result_size = 0;
return;
}
if (!xsup_assert((eapdata->eap_data != NULL), "eapdata->eap_data != NULL",
FALSE))
{
eap_type_common_fail(eapdata);
*result_size = 0;
return;
}
mytls_vars = (struct tls_vars *)eapdata->eap_data;
phase2 = (struct eapfast_phase2 *)mytls_vars->phase2data;
if (!xsup_assert((phase2->result_data != NULL),
"phase2->result_data != NULL", FALSE))
{
eap_type_common_fail(eapdata);
*result_size = 0;
return;
}
memcpy(result, phase2->result_data, phase2->result_size);
*result_size = phase2->result_size;
}
#endif // EAP_FAST
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?