예제 #1
0
static int
_gnutls_ia_client_handshake (gnutls_session_t session)
{
  char *buf = NULL;
  size_t buflen = 0;
  char tmp[1024];		/* XXX */
  ssize_t len;
  int ret;
  const struct gnutls_ia_client_credentials_st *cred =
    _gnutls_get_cred (session->key, GNUTLS_CRD_IA, NULL);

  if (cred == NULL)
    return GNUTLS_E_INTERNAL_ERROR;

  while (1)
    {
      char *avp;
      size_t avplen;

      ret = cred->avp_func (session, cred->avp_ptr,
			    buf, buflen, &avp, &avplen);
      if (ret)
	{
	  int tmpret;
	  tmpret = gnutls_alert_send (session, GNUTLS_AL_FATAL,
				      GNUTLS_A_INNER_APPLICATION_FAILURE);
	  if (tmpret < 0)
	    gnutls_assert ();
	  return ret;
	}

      len = gnutls_ia_send (session, avp, avplen);
      gnutls_free (avp);
      if (len < 0)
	return len;

      len = gnutls_ia_recv (session, tmp, sizeof (tmp));
      if (len == GNUTLS_E_WARNING_IA_IPHF_RECEIVED ||
	  len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED)
	{
	  ret = gnutls_ia_verify_endphase (session, tmp);
	  if (ret < 0)
	    return ret;

	  ret = gnutls_ia_endphase_send
	    (session, len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED);
	  if (ret < 0)
	    return ret;
	}

      if (len == GNUTLS_E_WARNING_IA_IPHF_RECEIVED)
	{
	  buf = NULL;
	  buflen = 0;
	  continue;
	}
      else if (len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED)
	break;

      if (len < 0)
	return len;

      buflen = len;
      buf = tmp;
    }

  return 0;
}
예제 #2
0
static int
_gnutls_ia_server_handshake (gnutls_session_t session)
{
  gnutls_ia_apptype_t msg_type;
  ssize_t len;
  char buf[1024];
  int ret;
  const struct gnutls_ia_server_credentials_st *cred =
    _gnutls_get_cred (session->key, GNUTLS_CRD_IA, NULL);

  if (cred == NULL)
    return GNUTLS_E_INTERNAL_ERROR;

  do
    {
      char *avp;
      size_t avplen;

      len = gnutls_ia_recv (session, buf, sizeof (buf));
      if (len == GNUTLS_E_WARNING_IA_IPHF_RECEIVED ||
	  len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED)
	{
	  ret = gnutls_ia_verify_endphase (session, buf);
	  if (ret < 0)
	    return ret;
	}

      if (len == GNUTLS_E_WARNING_IA_IPHF_RECEIVED)
	continue;
      else if (len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED)
	break;

      if (len < 0)
	return len;

      avp = NULL;
      avplen = 0;

      ret = cred->avp_func (session, cred->avp_ptr, buf, len, &avp, &avplen);
      if (ret < 0)
	{
	  int tmpret;
	  tmpret = gnutls_alert_send (session, GNUTLS_AL_FATAL,
				      GNUTLS_A_INNER_APPLICATION_FAILURE);
	  if (tmpret < 0)
	    gnutls_assert ();
	  return ret;
	}

      msg_type = ret;

      if (msg_type != GNUTLS_IA_APPLICATION_PAYLOAD)
	{
	  ret = gnutls_ia_endphase_send (session, msg_type ==
					 GNUTLS_IA_FINAL_PHASE_FINISHED);
	  if (ret < 0)
	    return ret;
	}
      else
	{
	  len = gnutls_ia_send (session, avp, avplen);
	  gnutls_free (avp);
	  if (len < 0)
	    return len;
	}
    }
  while (1);

  return 0;
}
예제 #3
0
int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
			   const u8 *in_data, size_t in_len,
			   u8 *out_data, size_t out_len)
{
	ssize_t res;

	if (conn->pull_buf) {
		wpa_printf(MSG_DEBUG, "%s - %d bytes remaining in "
			   "pull_buf", __func__, conn->pull_buf_len);
		os_free(conn->pull_buf);
	}
	conn->pull_buf = os_malloc(in_len);
	if (conn->pull_buf == NULL)
		return -1;
	os_memcpy(conn->pull_buf, in_data, in_len);
	conn->pull_buf_offset = conn->pull_buf;
	conn->pull_buf_len = in_len;

#ifdef GNUTLS_IA
	if (conn->tls_ia) {
		res = gnutls_ia_recv(conn->session, out_data, out_len);
		if (out_len >= 12 &&
		    (res == GNUTLS_E_WARNING_IA_IPHF_RECEIVED ||
		     res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED)) {
			int final = res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED;
			wpa_printf(MSG_DEBUG, "%s: Received %sPhaseFinished",
				   __func__, final ? "Final" : "Intermediate");

			res = gnutls_ia_permute_inner_secret(
				conn->session, conn->session_keys_len,
				conn->session_keys);
			if (conn->session_keys) {
				os_memset(conn->session_keys, 0,
					  conn->session_keys_len);
				os_free(conn->session_keys);
			}
			conn->session_keys = NULL;
			conn->session_keys_len = 0;
			if (res) {
				wpa_printf(MSG_DEBUG, "%s: Failed to permute "
					   "inner secret: %s",
					   __func__, gnutls_strerror(res));
				return -1;
			}

			res = gnutls_ia_verify_endphase(conn->session,
							out_data);
			if (res == 0) {
				wpa_printf(MSG_DEBUG, "%s: Correct endphase "
					   "checksum", __func__);
			} else {
				wpa_printf(MSG_INFO, "%s: Endphase "
					   "verification failed: %s",
					   __func__, gnutls_strerror(res));
				return -1;
			}

			if (final)
				conn->final_phase_finished = 1;

			return 0;
		}