eapfast_phase2.c

来自「linux 下通过802.1认证的安装包」· C语言 代码 · 共 1,907 行 · 第 1/4 页

C
1,907
字号
      fasttlv = (struct eapfast_tlv *)&phase2->result_data[phase2->result_size];

      fasttlv->type = htons(FAST_EAP_PAYLOAD_TLV | MANDATORY_TLV);
      fasttlv->length = htons(eapsize);
      phase2->result_size += eapsize + 4;  // 4 for 2 16 bit numbers that make
                                           // up the EAP-FAST TLV headers.
    }
  else
    {
      eap_type_common_fail(eapdata);
      return 0;
    }

  fasttlv = (struct eapfast_tlv *)indata;

  return ntohs(fasttlv->length) + 4;
}

/***************************************************************
 *
 *  Generate an error TLV.
 *
 ***************************************************************/
uint8_t *eapfast_phase2_gen_error_tlv(uint32_t reason, uint16_t mandatory)
{
  uint8_t *result;
  struct eapfast_tlv_error *error;

  if (result_tlv_included == FALSE) result_tlv_needed = TRUE;

  result = Malloc(sizeof(struct eapfast_tlv_error));
  if (result == NULL) return NULL;

  error = (struct eapfast_tlv_error *)result;

  error->type = htons(FAST_ERROR_TLV | mandatory);
  error->length = htons(sizeof(struct eapfast_tlv_error)-4);
  error->error_code = htonl(reason);

  return result;
}

/********************************************************************
 *
 *  Build a REQUEST_ACTION TLV response.
 *
 ********************************************************************/
uint8_t *eapfast_phase2_gen_request_action_tlv(uint16_t reason)
{
  uint8_t *result;
  struct eapfast_tlv_request_action *action;

  result = Malloc(sizeof(struct eapfast_tlv_request_action));
  if (result == NULL) return NULL;

  action = (struct eapfast_tlv_request_action *)result;

  action->type = htons(FAST_REQUEST_ACTION_TLV | MANDATORY_TLV);
  action->length = htons(sizeof(struct eapfast_tlv_request_action) - 4);
  action->action = htons(reason);

  return result;
}

/***************************************************************
 *
 *  Generate our own result TLV
 *
 ***************************************************************/
uint8_t *eapfast_phase2_get_result_tlv(uint16_t status)
{
  uint8_t *result;
  struct eapfast_tlv_result *resulttlv;

  result = Malloc(sizeof(struct eapfast_tlv_result));
  if (result == NULL) return NULL;

  resulttlv = (struct eapfast_tlv_result *)result;

  resulttlv->type = htons(FAST_RESULT_TLV | MANDATORY_TLV);
  resulttlv->length = htons(2);
  resulttlv->status = htons(status);

  return result;
}

/***************************************************************
 *
 *  Process a phase 2 result TLV message.
 *
 ***************************************************************/
uint16_t eapfast_phase2_process_result_tlv(eap_type_data *eapdata, 
					   uint8_t *indata, uint16_t insize)
{
  struct tls_vars *mytls_vars;
  struct eapfast_phase2 *phase2;
  struct eapfast_tlv_result *fasttlv;
  uint8_t *temp;

  if (!xsup_assert((eapdata != NULL), "eapdata != NULL", FALSE))
    return 0;

  if (!xsup_assert((eapdata->eap_data != NULL), "eapdata->eap_data != NULL",
		   FALSE))
    {
      eap_type_common_fail(eapdata);
      return 0;
    }

  mytls_vars = (struct tls_vars *)eapdata->eap_data;
  phase2 = (struct eapfast_phase2 *)mytls_vars->phase2data;

  fasttlv = (struct eapfast_tlv_result *)indata;

  if (ntohs(fasttlv->length) != 2)
    {
      debug_printf(DEBUG_NORMAL, "Got an invalid TLV_RESULT message!\n");
      temp = eapfast_phase2_gen_error_tlv(FAST_UNEXPECTED_TLVS_EXCHANGED,
					  (ntohs(fasttlv->type) & MANDATORY_TLV));

      memcpy(&phase2->result_data[phase2->result_size], temp, 
	     sizeof(struct eapfast_tlv_error));

      FREE(temp);
      phase2->result_size += sizeof(struct eapfast_tlv_error);
      return ntohs(fasttlv->length);
    }

  if ((ntohs(fasttlv->status) < 1) || (ntohs(fasttlv->status) > 2))
    {
      debug_printf(DEBUG_NORMAL, "Got an invalid result value in TLV_RESULT "
		   "message!  (Value was %d)\n", ntohs(fasttlv->status));
      temp = eapfast_phase2_gen_error_tlv(FAST_UNEXPECTED_TLVS_EXCHANGED,
					  (ntohs(fasttlv->type) & MANDATORY_TLV));

      memcpy(&phase2->result_data[phase2->result_size], temp,
             sizeof(struct eapfast_tlv_error));

      FREE(temp);
      phase2->result_size += sizeof(struct eapfast_tlv_error);
      return ntohs(fasttlv->length);
    }

  switch (ntohs(fasttlv->status))
    {
    case FAST_RESULT_SUCCESS:
      debug_printf(DEBUG_NORMAL, "Inner result is a success!\n");
      eapdata->methodState = CONT;
      eapdata->decision = COND_SUCC;
      break;

    case FAST_RESULT_FAILURE:
      debug_printf(DEBUG_NORMAL, "Inner result is a FAILURE!\n");
      eapdata->methodState = DONE;
      eapdata->decision = EAP_FAIL;
      break;
    }

  // Create our own result TLV to be sent back.
  temp = eapfast_phase2_get_result_tlv(ntohs(fasttlv->status));

  memcpy(&phase2->result_data[phase2->result_size], temp,
	 sizeof(struct eapfast_tlv_result));

  phase2->result_size += sizeof(struct eapfast_tlv_result);

  return sizeof(struct eapfast_tlv_result);
}

/***************************************************************
 *
 *  Generate our own intermediate result TLV
 *
 ***************************************************************/
uint8_t *eapfast_phase2_get_intermediate_result_tlv(uint16_t status)
{
  uint8_t *result;
  struct eapfast_tlv_result *resulttlv;

  result = Malloc(sizeof(struct eapfast_tlv_result));
  if (result == NULL) return NULL;

  resulttlv = (struct eapfast_tlv_result *)result;

  resulttlv->type = htons(FAST_INTERMEDIATE_RESULT_TLV | MANDATORY_TLV);
  resulttlv->length = htons(2);
  resulttlv->status = htons(status);

  return result;
}

/***************************************************************
 *
 *  Our crypto binding failed.  So, wipe out the data that we were
 *  building, and replace it with a result failure, and an error of
 *  binding failed.
 *
 ***************************************************************/
void eapfast_phase2_binding_failed(eap_type_data *eapdata)
{
  uint8_t *temp;
  struct tls_vars *mytls_vars;
  struct eapfast_phase2 *phase2;
  struct eapfast_tlv *tlv;

  if (!xsup_assert((eapdata != NULL), "eapdata != NULL", FALSE))
    return;

  mytls_vars = (struct tls_vars *)eapdata->eap_data;
  phase2 = (struct eapfast_phase2 *)mytls_vars->phase2data;

  // Clean out the existing data.
  FREE(phase2->result_data);
  phase2->result_size = 0;

  // Now allocate some new memory, and fill it.
  phase2->result_data = Malloc(1500);
  if (phase2->result_data == NULL)
    {
      debug_printf(DEBUG_NORMAL, "Couldn't allocate memory to store failure "
		   "data!\n");
      eap_type_common_fail(eapdata);
      return;
    }

  temp = eapfast_phase2_get_result_tlv(FAST_RESULT_FAILURE);
  tlv = (struct eapfast_tlv *)temp;

  memcpy(phase2->result_data, temp, ntohs(tlv->length)+4);
  phase2->result_size = ntohs(tlv->length)+4;

  FREE(temp);

  temp = eapfast_phase2_gen_error_tlv(FAST_TUNNEL_COMPROMISE_ERROR, 
				      MANDATORY_TLV);
  tlv = (struct eapfast_tlv *)temp;

  memcpy(&phase2->result_data[phase2->result_size], temp, 
	 ntohs(tlv->length)+4);

  phase2->result_size += ntohs(tlv->length)+4;

  debug_printf(DEBUG_AUTHTYPES, "Error result (%d) :\n", phase2->result_size);
  debug_hex_dump(DEBUG_AUTHTYPES, phase2->result_data, phase2->result_size);
}

/***************************************************************
 *
 *  Process an Intermedia result TLV.
 *
 ***************************************************************/
int eapfast_phase2_intermediate_result_process(eap_type_data *eapdata,
					       uint8_t *indata,
					       uint16_t insize)
{
  struct eapfast_tlv_result *fasttlv;
  struct tls_vars *mytls_vars;
  struct eapfast_phase2 *phase2;
  uint8_t *temp;

  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 >= 6), "insize >= 6", FALSE))
    {
      eap_type_common_fail(eapdata);
      return 0;
    }

  fasttlv = (struct eapfast_tlv_result *)indata;

  mytls_vars = (struct tls_vars *)eapdata->eap_data;
  phase2 = (struct eapfast_phase2 *)mytls_vars->phase2data;

  if ((ntohs(fasttlv->status) < 1) || (ntohs(fasttlv->status) > 2))
    {
      debug_printf(DEBUG_NORMAL, "Got an invalid result value in TLV_RESULT "
                   "message!  (Value was %d)\n", ntohs(fasttlv->status));
      temp = eapfast_phase2_gen_error_tlv(FAST_UNEXPECTED_TLVS_EXCHANGED,
                                          (ntohs(fasttlv->type) & MANDATORY_TLV));

      memcpy(&phase2->result_data[phase2->result_size], temp,
             sizeof(struct eapfast_tlv_error));

      FREE(temp);
      phase2->result_size += sizeof(struct eapfast_tlv_error);
      return ntohs(fasttlv->length);
    }

  switch (ntohs(fasttlv->status))
    {
    case FAST_RESULT_SUCCESS:
      debug_printf(DEBUG_NORMAL, "Intermediate result is a success!\n");
      break;

    case FAST_RESULT_FAILURE:
      debug_printf(DEBUG_NORMAL, "Intermediate result is a FAILURE!\n");
      break;
    }

  // Create our own result TLV to be sent back.
  temp = eapfast_phase2_get_intermediate_result_tlv(ntohs(fasttlv->status));

  memcpy(&phase2->result_data[phase2->result_size], temp,
         sizeof(struct eapfast_tlv_result));

  phase2->result_size += sizeof(struct eapfast_tlv_result);

  return sizeof(struct eapfast_tlv_result);
}

/****************************************************************
 *
 *  The T-PRF as specified in section 5.5 of draft-cam-winget-eap-fast-03.txt.
 *
 *  NOTE :  The value of result_size is the target we are shooting for.
 *  If it isn't a multiple of 20, then we will round up to the next value
 *  of 20, and return everything.  This shouldn't be a problem, since the
 *  caller will still get the data they need, and when the data is freed
 *  the extra memory will be freed as well.
 *
 ****************************************************************/
uint8_t *eapfast_phase2_t_prf(uint8_t *key, uint16_t keylen, char *label,
			      uint8_t *seed, uint16_t seedlen, 
			      uint16_t result_size)
{
  uint8_t *s = NULL, *result = NULL, *feed = NULL;
  uint16_t length, i, sizeofs, sizeoffeed;
  uint8_t mac[20];
  unsigned int mdlen;

  if (!xsup_assert((key != NULL), "key != NULL", FALSE))
    return NULL;

  if (!xsup_assert((label != NULL), "label != NULL", FALSE))
    return NULL;

  if ((result_size % 20) == 0)
    {
      length = result_size;
    }
  else
    {
      length = (20 - (result_size % 20)) + result_size;
    }

  result = Malloc(length);
  if (result == NULL)
    {
      debug_printf(DEBUG_NORMAL, "Couldn't allocate memory to create the "
		   "T-PRF values!\n");
      return NULL;
    }

  s = Malloc(strlen(label) + 1 + seedlen);  
  if (s == NULL)
    {
      debug_printf(DEBUG_NORMAL, "Couldn't allocate memory to create 'S' in "
		   "the T-PRF!\n");
      FREE(result);
      return NULL;
    }

  // Create the "S".
  strcpy(s, label);
  s[strlen(label)] = 0x00;

  if (seed != NULL)
    {
      memcpy(&s[strlen(label)+1], seed, seedlen);
    }

  sizeofs = strlen(label) + 1 + seedlen;

  // Now, hash the number of times needed to generate the right amount of
  // material.
  for (i = 0;i < (length/20);i++)
    {
      if (i == 0)
	{
	  feed = Malloc(sizeofs+4);
	  if (feed == NULL)
	    {
	      debug_printf(DEBUG_NORMAL, "Couldn't allocate temporary space "
			   "to store 'to hash' data!\n");
	      FREE(result);
	      FREE(s);
	      return NULL;
	    }

	  memcpy(feed, s, sizeofs);
	  sizeoffeed = sizeofs;

	  feed[sizeoffeed] = (result_size >> 8);
	  feed[sizeoffeed+1] = (result_size & 0xff);
	  sizeoffeed+=2;
	  feed[sizeoffeed] = 0x01;
	  sizeoffeed++;
	}
      else
	{
	  feed = Malloc(sizeofs+20+3);
	  if (feed == NULL)
	    {
	      debug_printf(DEBUG_NORMAL, "Couldn't allocate temporary space "
			   "to store 'to hash' data!\n");
	      FREE(result);
	      FREE(s);
	      return NULL;
	    }

	  memcpy(feed, &result[(i-1)*20], 20);
	  memcpy(&feed[20], s, sizeofs);
	  sizeoffeed = 20 + sizeofs;
	  feed[sizeoffeed] = (result_size >> 8);
	  feed[sizeoffeed+1] = (result_size & 0xff);
	  sizeoffeed += 2;
	  feed[sizeoffeed] = (i+1);
	  sizeoffeed++;
	}

      HMAC(EVP_sha1(), key, keylen, feed, sizeoffeed, (unsigned char *)&mac, 
	   &mdlen);
      memcpy(&result[i*20], mac, 20);

      FREE(feed);
      sizeoffeed = 0;
    }

  return result;
}

/*****************************************************************
 *
 *  Return the current S-IMCK[j].
 *
 *****************************************************************/
uint8_t *eapfast_phase2_get_simckj(eap_type_data *eapdata)
{
  struct tls_vars *mytls_vars;
  struct eapfast_phase2 *phase2;

  if (!xsup_assert((eapdata != NULL), "eapdata != NULL", FALSE))
    return NULL;

  mytls_vars = (struct tls_vars *)eapdata->eap_data;
  phase2 = (struct eapfast_phase2 *)mytls_vars->phase2data;

  return phase2->simckj;
}

/****************************************************************
 *
 *  Generate the CMK[j] needed to check the compound MAC.
 *
 ****************************************************************/
uint8_t *eapfast_phase2_gen_cmkj(eap_type_data *eapdata)
{
  struct tls_vars *mytls_vars;
  struct eapfast_phase2 *phase2;
  uint8_t *keyblock;
  uint8_t *key;
  uint8_t *cmkj;

  if (!xsup_assert((eapdata != NULL), "eapdata != NULL", FALSE))
    return NULL;

  mytls_vars = (struct tls_vars *)eapdata->eap_data;
  phase2 = (struct eapfast_phase2 *)mytls_vars->phase2data;

  debug_printf(DEBUG_AUTHTYPES, "Key data :\n");

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?