Example #1
0
static int
client_send(gnutls_session_t session,
	    gnutls_buffer_st * extdata, status_request_ext_st * priv)
{
	int ret_len = 1 + 2;
	int ret;
	size_t i;

	ret = _gnutls_buffer_append_prefix(extdata, 8, 1);
	if (ret < 0)
		return gnutls_assert_val(ret);

	ret =
	    _gnutls_buffer_append_prefix(extdata, 16,
					 priv->responder_id_size);
	if (ret < 0)
		return gnutls_assert_val(ret);

	for (i = 0; i < priv->responder_id_size; i++) {
		if (priv->responder_id[i].size <= 0)
			return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

		ret = _gnutls_buffer_append_data_prefix(extdata, 16,
							priv->
							responder_id[i].
							data,
							priv->
							responder_id[i].
							size);
		if (ret < 0)
			return gnutls_assert_val(ret);

		ret_len += 2 + priv->responder_id[i].size;
	}

	ret = _gnutls_buffer_append_data_prefix(extdata, 16,
						priv->request_extensions.
						data,
						priv->request_extensions.
						size);
	if (ret < 0)
		return gnutls_assert_val(ret);

	ret_len += 2 + priv->request_extensions.size;

	return ret_len;
}
Example #2
0
/* returns data_size or a negative number on failure
 */
static int
_gnutls_supported_ecc_send_params(gnutls_session_t session,
				  gnutls_buffer_st * extdata)
{
	unsigned len, i;
	int ret;
	uint16_t p;

	/* this extension is only being sent on client side */
	if (session->security_parameters.entity == GNUTLS_CLIENT) {

		if (session->internals.priorities.supported_ecc.
		    algorithms > 0) {

			len =
			    session->internals.priorities.supported_ecc.
			    algorithms;

			/* this is a vector!
			 */
			ret =
			    _gnutls_buffer_append_prefix(extdata, 16,
							 len * 2);
			if (ret < 0)
				return gnutls_assert_val(ret);

			for (i = 0; i < len; i++) {
				p = _gnutls_ecc_curve_get_tls_id(session->
								 internals.
								 priorities.supported_ecc.
								 priority
								 [i]);
				ret =
				    _gnutls_buffer_append_prefix(extdata,
								 16, p);
				if (ret < 0)
					return gnutls_assert_val(ret);
			}
			return (len + 1) * 2;
		}

	}

	return 0;
}
Example #3
0
/* If the psk flag is set, then an empty psk_identity_hint will
 * be inserted */
int _gnutls_ecdh_common_print_server_kx(gnutls_session_t session,
					gnutls_buffer_st * data,
					gnutls_ecc_curve_t curve)
{
	uint8_t p;
	int ret;
	gnutls_datum_t out;

	if (curve == GNUTLS_ECC_CURVE_INVALID)
		return gnutls_assert_val(GNUTLS_E_ECC_NO_SUPPORTED_CURVES);

	/* just in case we are resuming a session */
	gnutls_pk_params_release(&session->key.ecdh_params);

	gnutls_pk_params_init(&session->key.ecdh_params);

	/* curve type */
	p = 3;

	ret = _gnutls_buffer_append_data(data, &p, 1);
	if (ret < 0)
		return gnutls_assert_val(ret);

	ret =
	    _gnutls_buffer_append_prefix(data, 16,
					 _gnutls_ecc_curve_get_tls_id
					 (curve));
	if (ret < 0)
		return gnutls_assert_val(ret);

	/* generate temporal key */
	ret =
	    _gnutls_pk_generate_keys(GNUTLS_PK_EC, curve,
				     &session->key.ecdh_params);
	if (ret < 0)
		return gnutls_assert_val(ret);

	ret =
	    _gnutls_ecc_ansi_x963_export(curve,
					 session->key.ecdh_params.
					 params[ECC_X] /* x */ ,
					 session->key.ecdh_params.
					 params[ECC_Y] /* y */ , &out);
	if (ret < 0)
		return gnutls_assert_val(ret);

	ret =
	    _gnutls_buffer_append_data_prefix(data, 8, out.data, out.size);

	_gnutls_free_datum(&out);

	if (ret < 0)
		return gnutls_assert_val(ret);

	return data->length;
}
Example #4
0
static int
gen_dhe_psk_server_kx(gnutls_session_t session, gnutls_buffer_st * data)
{
	bigint_t g, p;
	const bigint_t *mpis;
	int ret;
	gnutls_dh_params_t dh_params;
	gnutls_psk_server_credentials_t cred;

	cred = (gnutls_psk_server_credentials_t)
	    _gnutls_get_cred(session, GNUTLS_CRD_PSK, NULL);
	if (cred == NULL) {
		gnutls_assert();
		return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
	}

	dh_params =
	    _gnutls_get_dh_params(cred->dh_params, cred->params_func,
				  session);
	mpis = _gnutls_dh_params_to_mpi(dh_params);
	if (mpis == NULL) {
		gnutls_assert();
		return GNUTLS_E_NO_TEMPORARY_DH_PARAMS;
	}

	p = mpis[0];
	g = mpis[1];

	if ((ret =
	     _gnutls_auth_info_set(session, GNUTLS_CRD_PSK,
				   sizeof(psk_auth_info_st), 1)) < 0) {
		gnutls_assert();
		return ret;
	}

	_gnutls_dh_set_group(session, g, p);

	ret = _gnutls_buffer_append_prefix(data, 16, 0);
	if (ret < 0)
		return gnutls_assert_val(ret);

	ret =
	    _gnutls_dh_common_print_server_kx(session, g, p,
					      dh_params->q_bits, data);
	if (ret < 0)
		gnutls_assert();

	return ret;
}
Example #5
0
static int
server_send_params(gnutls_session_t session, gnutls_buffer_t extdata)
{
	int ret;

	if (!(session->internals.hsk_flags & HSK_PSK_SELECTED))
		return 0;

	ret = _gnutls_buffer_append_prefix(extdata, 16,
					   session->key.binders[0].idx);
	if (ret < 0)
		return gnutls_assert_val(ret);

	return 2;
}
Example #6
0
static int append_nst_extension(void *ctx, gnutls_buffer_st *buf)
{
	gnutls_session_t session = ctx;
	int ret;

	if (!(session->internals.flags & GNUTLS_ENABLE_EARLY_DATA))
		return 0;

	ret = _gnutls_buffer_append_prefix(buf, 32,
					   session->security_parameters.
					   max_early_data_size);
	if (ret < 0)
		gnutls_assert();

	return ret;
}
Example #7
0
int
_gnutls_buffer_append_data_prefix (gnutls_buffer_st * buf, 
    int pfx_size, const void *data, size_t data_size)
{
int ret = 0, ret1;

  ret1 = _gnutls_buffer_append_prefix (buf, pfx_size, data_size);
  if (ret1 < 0)
    return gnutls_assert_val(ret1);

  if (data_size > 0)
    {
      ret = _gnutls_buffer_append_data (buf, data, data_size);

      if (ret < 0)
        return gnutls_assert_val(ret);
    }

  return ret + ret1;
}
Example #8
0
static int
gen_ecdhe_psk_server_kx(gnutls_session_t session, gnutls_buffer_st * data)
{
	int ret;

	if ((ret =
	     _gnutls_auth_info_set(session, GNUTLS_CRD_PSK,
				   sizeof(psk_auth_info_st), 1)) < 0) {
		gnutls_assert();
		return ret;
	}

	ret = _gnutls_buffer_append_prefix(data, 16, 0);
	if (ret < 0)
		return gnutls_assert_val(ret);

	ret = _gnutls_ecdh_common_print_server_kx(session, data,
						  _gnutls_session_ecc_curve_get
						  (session));
	if (ret < 0)
		gnutls_assert();

	return ret;
}
Example #9
0
/* returns data_size or a negative number on failure
 */
static int
_gnutls_server_name_send_params(gnutls_session_t session,
				gnutls_buffer_st * extdata)
{
	uint16_t len;
	unsigned i;
	int total_size = 0, ret;
	server_name_ext_st *priv;
	extension_priv_data_t epriv;

	ret =
	    _gnutls_ext_get_session_data(session,
					 GNUTLS_EXTENSION_SERVER_NAME,
					 &epriv);
	if (ret < 0)
		return 0;


	/* this function sends the client extension data (dnsname)
	 */
	if (session->security_parameters.entity == GNUTLS_CLIENT) {
		priv = epriv;

		if (priv->server_names_size == 0)
			return 0;

		/* uint16_t
		 */
		total_size = 2;
		for (i = 0; i < priv->server_names_size; i++) {
			/* count the total size
			 */
			len = priv->server_names[i].name_length;

			/* uint8_t + uint16_t + size
			 */
			total_size += 1 + 2 + len;
		}

		/* UINT16: write total size of all names
		 */
		ret =
		    _gnutls_buffer_append_prefix(extdata, 16,
						 total_size - 2);
		if (ret < 0)
			return gnutls_assert_val(ret);

		for (i = 0; i < priv->server_names_size; i++) {

			switch (priv->server_names[i].type) {
			case GNUTLS_NAME_DNS:
				len = priv->server_names[i].name_length;
				if (len == 0)
					break;

				/* UINT8: type of this extension
				 * UINT16: size of the first name
				 * LEN: the actual server name.
				 */
				ret =
				    _gnutls_buffer_append_prefix(extdata,
								 8, 0);
				if (ret < 0)
					return gnutls_assert_val(ret);

				ret =
				    _gnutls_buffer_append_data_prefix
				    (extdata, 16,
				     priv->server_names[i].name, len);
				if (ret < 0)
					return gnutls_assert_val(ret);

				break;
			default:
				gnutls_assert();
				return GNUTLS_E_INTERNAL_ERROR;
			}
		}
	}

	return total_size;
}
Example #10
0
int _gnutls13_send_certificate(gnutls_session_t session, unsigned again)
{
	int ret;
	gnutls_pcert_st *apr_cert_list = NULL;
	gnutls_privkey_t apr_pkey = NULL;
	int apr_cert_list_length = 0;
	mbuffer_st *bufel = NULL;
	gnutls_buffer_st buf;
	unsigned pos_mark, ext_pos_mark;
	unsigned i;
	struct ocsp_req_ctx_st ctx;
	gnutls_certificate_credentials_t cred;

	if (again == 0) {
		if (!session->internals.initial_negotiation_completed &&
		    session->internals.hsk_flags & HSK_PSK_SELECTED)
			return 0;

		if (session->security_parameters.entity == GNUTLS_SERVER &&
		    session->internals.resumed)
			return 0;

		cred = (gnutls_certificate_credentials_t)
		    _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE);
		if (cred == NULL) {
			gnutls_assert();
			return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
		}

		if (session->security_parameters.entity == GNUTLS_CLIENT &&
		    !(session->internals.hsk_flags & HSK_CRT_ASKED)) {
			return 0;
		}

		ret = _gnutls_get_selected_cert(session, &apr_cert_list,
						&apr_cert_list_length, &apr_pkey);
		if (ret < 0)
			return gnutls_assert_val(ret);

		ret = _gnutls_buffer_init_handshake_mbuffer(&buf);
		if (ret < 0)
			return gnutls_assert_val(ret);

		if (session->security_parameters.entity == GNUTLS_CLIENT) {
			ret = _gnutls_buffer_append_data_prefix(&buf, 8,
								session->internals.post_handshake_cr_context.data,
								session->internals.post_handshake_cr_context.size);
			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}

		} else {
			ret = _gnutls_buffer_append_prefix(&buf, 8, 0);
			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}
		}

		/* mark total size */
		pos_mark = buf.length;
		ret = _gnutls_buffer_append_prefix(&buf, 24, 0);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		for (i=0;i<(unsigned)apr_cert_list_length;i++) {
			ret = _gnutls_buffer_append_data_prefix(&buf, 24,
								apr_cert_list[i].cert.data,
								apr_cert_list[i].cert.size);
			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}

#ifdef ENABLE_OCSP
			if ((session->internals.selected_ocsp_length > 0 ||
			     session->internals.selected_ocsp_func) &&
			    _gnutls_hello_ext_is_present(session, GNUTLS_EXTENSION_STATUS_REQUEST)) {
				/* append status response if available */
				ret = _gnutls_extv_append_init(&buf);
				if (ret < 0) {
					gnutls_assert();
					goto cleanup;
				}
				ext_pos_mark = ret;

				ctx.pcert = &apr_cert_list[i];
				ctx.cert_index = i;
				ctx.session = session;
				ctx.cred = cred;
				ret = _gnutls_extv_append(&buf, STATUS_REQUEST_TLS_ID,
							  &ctx, append_status_request);
				if (ret < 0) {
					gnutls_assert();
					goto cleanup;
				}

				ret = _gnutls_extv_append_final(&buf, ext_pos_mark, 0);
				if (ret < 0) {
					gnutls_assert();
					goto cleanup;
				}
			} else
#endif
			{
				ret = _gnutls_buffer_append_prefix(&buf, 16, 0);
				if (ret < 0) {
					gnutls_assert();
					goto cleanup;
				}
			}
		}

		_gnutls_write_uint24(buf.length-pos_mark-3, &buf.data[pos_mark]);

		bufel = _gnutls_buffer_to_mbuffer(&buf);
	}

	return _gnutls_send_handshake(session, bufel, GNUTLS_HANDSHAKE_CERTIFICATE_PKT);

 cleanup:
	_gnutls_buffer_clear(&buf);
	return ret;
}
int
_gnutls_gen_extensions(gnutls_session_t session,
		       gnutls_buffer_st * extdata,
		       gnutls_ext_parse_type_t parse_type)
{
	int size;
	int pos, size_pos, ret;
	size_t i, init_size = extdata->length;

	pos = extdata->length;	/* we will store length later on */

	ret = _gnutls_buffer_append_prefix(extdata, 16, 0);
	if (ret < 0)
		return gnutls_assert_val(ret);

	for (i = 0; i < extfunc_size; i++) {
		extension_entry_st *p = &extfunc[i];

		if (p->send_func == NULL)
			continue;

		if (parse_type != GNUTLS_EXT_ANY
		    && p->parse_type != parse_type)
			continue;

		ret = _gnutls_buffer_append_prefix(extdata, 16, p->type);
		if (ret < 0)
			return gnutls_assert_val(ret);

		size_pos = extdata->length;
		ret = _gnutls_buffer_append_prefix(extdata, 16, 0);
		if (ret < 0)
			return gnutls_assert_val(ret);

		size = p->send_func(session, extdata);
		/* returning GNUTLS_E_INT_RET_0 means to send an empty
		 * extension of this type.
		 */
		if (size > 0 || size == GNUTLS_E_INT_RET_0) {
			if (size == GNUTLS_E_INT_RET_0)
				size = 0;

			/* write the real size */
			_gnutls_write_uint16(size,
					     &extdata->data[size_pos]);

			/* add this extension to the extension list
			 */
			_gnutls_extension_list_add(session, p->type);

			_gnutls_handshake_log
			    ("EXT[%p]: Sending extension %s (%d bytes)\n",
			     session, p->name, size);
		} else if (size < 0) {
			gnutls_assert();
			return size;
		} else if (size == 0)
			extdata->length -= 4;	/* reset type and size */
	}

	/* remove any initial data, and the size of the header */
	size = extdata->length - init_size - 2;

	if (size > 0)
		_gnutls_write_uint16(size, &extdata->data[pos]);
	else if (size == 0)
		extdata->length -= 2;	/* the length bytes */

	return size;
}
Example #12
0
     static int _proxyinfo_send_params (gnutls_session_t session, gnutls_buffer_st* extdata)
     {
//printf("Send params\n");
  uint16_t len;
  unsigned i;
  int total_size = 0, ret;
  ProxyInfo_ext_st *priv;
  extension_priv_data_t epriv;

  ret =
    _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_PROXYINFO,
                                  &epriv);
  if (ret < 0)
    return 0;


  /* this function sends the client extension data (dnsname)
   */
  if (session->security_parameters.entity == GNUTLS_CLIENT)
    {
      priv = epriv.ptr;

      if (priv->server_names_size == 0)
        return 0;

      /* uint16_t
       */
      total_size = 2;
      total_size+=2; //2 byte for 16 bit integer proxy_count
      total_size+=(sizeof(gnutls_ProxyInfo_ext)/2)*((priv->proxy_cnt)+1);
      for (i = 0; i < priv->server_names_size; i++)
        {
          /* count the total size
           */
          len = priv->server_names[i].name_length;

          /* uint8_t + uint16_t + size
           */
          total_size += 1 + 2 + len;
        }

      /* UINT16: write total size of all names
       */

      ret = _gnutls_buffer_append_prefix(extdata, 16, total_size - 2);
      ret = _gnutls_buffer_append_prefix(extdata, 16, priv->proxy_cnt);
      int count=priv->proxy_cnt;
      for(int proxy_id=0;proxy_id<count+1;proxy_id++){
      ret = _gnutls_buffer_append_prefix(extdata, 16, priv->proxy_info[proxy_id].cipher_algo);
      ret = _gnutls_buffer_append_prefix(extdata, 16, priv->proxy_info[proxy_id].kx_algo);
      ret = _gnutls_buffer_append_prefix(extdata, 16, priv->proxy_info[proxy_id].mac_algo);
      ret = _gnutls_buffer_append_prefix(extdata, 16, priv->proxy_info[proxy_id].ip_addr);
      ret = _gnutls_buffer_append_prefix(extdata, 16, priv->proxy_info[proxy_id].mac_addr);
      }
              
      if (ret < 0)
        return gnutls_assert_val(ret);

      for (i = 0; i < priv->server_names_size; i++)
        {

          switch (priv->server_names[i].type)
            {
            case GNUTLS_NAME_DNS:
              len = priv->server_names[i].name_length;
              if (len == 0)
                break;

              /* UINT8: type of this extension
               * UINT16: size of the first name
               * LEN: the actual server name.
               */
              ret = _gnutls_buffer_append_prefix(extdata, 8, 0);
              if (ret < 0)
                return gnutls_assert_val(ret);

              ret = _gnutls_buffer_append_data_prefix(extdata, 16, priv->server_names[i].name, len);
              if (ret < 0)
                return gnutls_assert_val(ret);

              break;
            default:
              gnutls_assert ();
              return GNUTLS_E_INTERNAL_ERROR;
            }
        }
    }

  return total_size;
     }
Example #13
0
static int
client_send_params(gnutls_session_t session,
		   gnutls_buffer_t extdata,
		   const gnutls_psk_client_credentials_t cred)
{
	int ret, ext_offset = 0;
	uint8_t binder_value[MAX_HASH_SIZE];
	size_t spos;
	gnutls_datum_t username = {NULL, 0};
	gnutls_datum_t user_key = {NULL, 0}, rkey = {NULL, 0};
	gnutls_datum_t client_hello;
	unsigned next_idx;
	const mac_entry_st *prf_res = NULL;
	const mac_entry_st *prf_psk = NULL;
	struct timespec cur_time;
	uint32_t ticket_age, ob_ticket_age;
	int free_username = 0;
	psk_auth_info_t info = NULL;
	unsigned psk_id_len = 0;
	unsigned binders_len, binders_pos;

	if (((session->internals.flags & GNUTLS_NO_TICKETS) ||
	    session->internals.tls13_ticket.ticket.data == NULL) &&
	    (!cred || !_gnutls_have_psk_credentials(cred, session))) {

		return 0;
	}

	binders_len = 0;

	/* placeholder to be filled later */
	spos = extdata->length;
	ret = _gnutls_buffer_append_prefix(extdata, 16, 0);
	if (ret < 0)
		return gnutls_assert_val(ret);

	/* First, let's see if we have a session ticket to send */
	if (!(session->internals.flags & GNUTLS_NO_TICKETS) &&
	    session->internals.tls13_ticket.ticket.data != NULL) {
		/* We found a session ticket */
		if (unlikely(session->internals.tls13_ticket.prf == NULL)) {
			_gnutls13_session_ticket_unset(session);
			ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
			goto cleanup;
		}

		prf_res = session->internals.tls13_ticket.prf;

		gnutls_gettime(&cur_time);
		if (unlikely(_gnutls_timespec_cmp(&cur_time,
						  &session->internals.
						  tls13_ticket.
						  arrival_time) < 0)) {
			gnutls_assert();
			_gnutls13_session_ticket_unset(session);
			goto ignore_ticket;
		}

		/* Check whether the ticket is stale */
		ticket_age = timespec_sub_ms(&cur_time,
					     &session->internals.tls13_ticket.
					     arrival_time);
		if (ticket_age / 1000 > session->internals.tls13_ticket.lifetime) {
			_gnutls13_session_ticket_unset(session);
			goto ignore_ticket;
		}

		ret = compute_psk_from_ticket(&session->internals.tls13_ticket, &rkey);
		if (ret < 0) {
			_gnutls13_session_ticket_unset(session);
			goto ignore_ticket;
		}

		/* Calculate obfuscated ticket age, in milliseconds, mod 2^32 */
		ob_ticket_age = ticket_age + session->internals.tls13_ticket.age_add;

		if ((ret = _gnutls_buffer_append_data_prefix(extdata, 16,
							     session->internals.tls13_ticket.ticket.data,
							     session->internals.tls13_ticket.ticket.size)) < 0) {
			gnutls_assert();
			goto cleanup;
		}

		/* Now append the obfuscated ticket age */
		if ((ret = _gnutls_buffer_append_prefix(extdata, 32, ob_ticket_age)) < 0) {
			gnutls_assert();
			goto cleanup;
		}

		psk_id_len += 6 + session->internals.tls13_ticket.ticket.size;
		binders_len += 1 + _gnutls_mac_get_algo_len(prf_res);
	}

 ignore_ticket:
	if (cred && _gnutls_have_psk_credentials(cred, session)) {
		gnutls_datum_t tkey;

		if (cred->binder_algo == NULL) {
			gnutls_assert();
			ret = gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
			goto cleanup;
		}

		prf_psk = cred->binder_algo;

		ret = _gnutls_find_psk_key(session, cred, &username, &tkey, &free_username);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		if (username.size == 0 || username.size > UINT16_MAX) {
			ret = gnutls_assert_val(GNUTLS_E_INVALID_PASSWORD);
			goto cleanup;
		}

		if (!free_username) {
			/* we need to copy the key */
			ret = _gnutls_set_datum(&user_key, tkey.data, tkey.size);
			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}
		} else {
			user_key.data = tkey.data;
			user_key.size = tkey.size;
		}

		ret = _gnutls_auth_info_init(session, GNUTLS_CRD_PSK, sizeof(psk_auth_info_st), 1);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
		assert(info != NULL);

		memcpy(info->username, username.data, username.size);
		info->username[username.size] = 0;

		if ((ret = _gnutls_buffer_append_data_prefix(extdata, 16,
							     username.data,
							     username.size)) < 0) {
			gnutls_assert();
			goto cleanup;
		}

		/* Now append the obfuscated ticket age */
		if ((ret = _gnutls_buffer_append_prefix(extdata, 32, 0)) < 0) {
			gnutls_assert();
			goto cleanup;
		}

		psk_id_len += 6 + username.size;
		binders_len += 1 + _gnutls_mac_get_algo_len(prf_psk);
	}

	/* if no tickets or identities to be sent */
	if (psk_id_len == 0) {
		/* reset extensions buffer */
		extdata->length = spos;
		return 0;
	}

	_gnutls_write_uint16(psk_id_len, &extdata->data[spos]);

	binders_pos = extdata->length-spos;
	ext_offset = _gnutls_ext_get_extensions_offset(session);

	/* Compute the binders. extdata->data points to the start
	 * of this client hello. */
	assert(extdata->length >= sizeof(mbuffer_st));
	assert(ext_offset >= (ssize_t)sizeof(mbuffer_st));
	ext_offset -= sizeof(mbuffer_st);
	client_hello.data = extdata->data+sizeof(mbuffer_st);
	client_hello.size = extdata->length-sizeof(mbuffer_st);

	next_idx = 0;

	ret = _gnutls_buffer_append_prefix(extdata, 16, binders_len);
	if (ret < 0) {
		gnutls_assert_val(ret);
		goto cleanup;
	}

	if (prf_res && rkey.size > 0) {
		ret = compute_psk_binder(session, prf_res,
					 binders_len, binders_pos,
					 ext_offset, &rkey, &client_hello, 1,
					 binder_value);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		/* Associate the selected pre-shared key with the session */
		gnutls_free(session->key.binders[next_idx].psk.data);
		session->key.binders[next_idx].psk.data = rkey.data;
		session->key.binders[next_idx].psk.size = rkey.size;
		rkey.data = NULL;

		session->key.binders[next_idx].prf = prf_res;
		session->key.binders[next_idx].resumption = 1;
		session->key.binders[next_idx].idx = next_idx;

		_gnutls_handshake_log("EXT[%p]: sent PSK resumption identity (%d)\n", session, next_idx);

		next_idx++;

		/* Add the binder */
		ret = _gnutls_buffer_append_data_prefix(extdata, 8, binder_value, prf_res->output_size);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		session->internals.hsk_flags |= HSK_TLS13_TICKET_SENT;
	}

	if (prf_psk && user_key.size > 0 && info) {
		ret = compute_psk_binder(session, prf_psk,
					 binders_len, binders_pos,
					 ext_offset, &user_key, &client_hello, 0,
					 binder_value);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		/* Associate the selected pre-shared key with the session */
		gnutls_free(session->key.binders[next_idx].psk.data);
		session->key.binders[next_idx].psk.data = user_key.data;
		session->key.binders[next_idx].psk.size = user_key.size;
		user_key.data = NULL;

		session->key.binders[next_idx].prf = prf_psk;
		session->key.binders[next_idx].resumption = 0;
		session->key.binders[next_idx].idx = next_idx;

		_gnutls_handshake_log("EXT[%p]: sent PSK identity '%s' (%d)\n", session, info->username, next_idx);

		next_idx++;

		/* Add the binder */
		ret = _gnutls_buffer_append_data_prefix(extdata, 8, binder_value, prf_psk->output_size);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}
	}

	ret = 0;

cleanup:
	if (free_username)
		_gnutls_free_datum(&username);

	_gnutls_free_temp_key_datum(&user_key);
	_gnutls_free_temp_key_datum(&rkey);

	return ret;
}
Example #14
0
static int
_gnutls_srtp_send_params(gnutls_session_t session,
			 gnutls_buffer_st * extdata)
{
	unsigned i;
	int total_size = 0, ret;
	srtp_ext_st *priv;
	extension_priv_data_t epriv;

	ret =
	    _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_SRTP,
					 &epriv);
	if (ret < 0)
		return 0;

	priv = epriv;

	if (priv->profiles_size == 0)
		return 0;

	if (session->security_parameters.entity == GNUTLS_SERVER) {
		/* Don't send anything if no matching profile was found */
		if (priv->selected_profile == 0)
			return 0;

		ret = _gnutls_buffer_append_prefix(extdata, 16, 2);
		if (ret < 0)
			return gnutls_assert_val(ret);
		ret =
		    _gnutls_buffer_append_prefix(extdata, 16,
						 priv->selected_profile);
		if (ret < 0)
			return gnutls_assert_val(ret);
		total_size = 4;
	} else {
		ret =
		    _gnutls_buffer_append_prefix(extdata, 16,
						 2 * priv->profiles_size);
		if (ret < 0)
			return gnutls_assert_val(ret);

		for (i = 0; i < priv->profiles_size; i++) {
			ret =
			    _gnutls_buffer_append_prefix(extdata, 16,
							 priv->
							 profiles[i]);
			if (ret < 0)
				return gnutls_assert_val(ret);
		}
		total_size = 2 + 2 * priv->profiles_size;
	}

	/* use_mki */
	ret =
	    _gnutls_buffer_append_data_prefix(extdata, 8, priv->mki,
					      priv->mki_size);
	if (ret < 0)
		return gnutls_assert_val(ret);
	total_size += 1 + priv->mki_size;

	return total_size;
}
Example #15
0
static int
_gnutls_alpn_send_params (gnutls_session_t session,
                          gnutls_buffer_st* extdata)
{
  unsigned i;
  int total_size = 0, ret;
  alpn_ext_st *priv;
  extension_priv_data_t epriv;

  ret =
    _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_ALPN,
                                  &epriv);
  if (ret < 0)
    return 0;

  priv = epriv.ptr;

  if (priv->size == 0)
    return 0;

  if (session->security_parameters.entity == GNUTLS_SERVER)
    {
      if (priv->selected_protocol_size == 0)
        return 0;

      ret = _gnutls_buffer_append_prefix(extdata, 16, priv->selected_protocol_size+1);
      if (ret < 0)
        return gnutls_assert_val(ret);

      total_size += 2;

      ret = _gnutls_buffer_append_data_prefix(extdata, 8, priv->selected_protocol, priv->selected_protocol_size);
      if (ret < 0)
        return gnutls_assert_val(ret);

      total_size += 1+priv->selected_protocol_size;
    }
  else
    {
      int t = 0;
      for (i=0;i<priv->size;i++)
        t += priv->protocol_size[i] + 1;

      ret = _gnutls_buffer_append_prefix(extdata, 16, t);
      if (ret < 0)
        return gnutls_assert_val(ret);

      total_size += 2;

      for (i=0;i<priv->size;i++)
        {
          ret = _gnutls_buffer_append_data_prefix(extdata, 8, priv->protocols[i], priv->protocol_size[i]);
          if (ret < 0)
            return gnutls_assert_val(ret);

          total_size += 1+priv->protocol_size[i];
        }
    }

  return total_size;
}
Example #16
0
int _gnutls13_send_session_ticket(gnutls_session_t session, unsigned nr, unsigned again)
{
	int ret = 0;
	mbuffer_st *bufel = NULL;
	gnutls_buffer_st buf;
	tls13_ticket_st ticket;
	unsigned i;

	/* Client does not send a NewSessionTicket */
	if (unlikely(session->security_parameters.entity == GNUTLS_CLIENT))
		return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);

	/* Session resumption has not been enabled */
	if (session->internals.flags & GNUTLS_NO_TICKETS)
		return gnutls_assert_val(0);

	/* If we received the psk_key_exchange_modes extension which
	 * does not have overlap with the server configuration, don't
	 * send a session ticket */
	if (session->internals.hsk_flags & HSK_PSK_KE_MODE_INVALID)
		return gnutls_assert_val(0);

	if (again == 0) {
		for (i=0;i<nr;i++) {
			unsigned init_pos;

			memset(&ticket, 0, sizeof(tls13_ticket_st));
			bufel = NULL;

			ret = _gnutls_buffer_init_handshake_mbuffer(&buf);
			if (ret < 0)
				return gnutls_assert_val(ret);

			ret = generate_session_ticket(session, &ticket);
			if (ret < 0) {
				if (ret == GNUTLS_E_INT_RET_0) {
					ret = gnutls_assert_val(0);
					goto cleanup;
				}
				gnutls_assert();
				goto cleanup;
			}

			ret = _gnutls_buffer_append_prefix(&buf, 32, ticket.lifetime);
			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}

			ret = _gnutls_buffer_append_prefix(&buf, 32, ticket.age_add);
			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}

			/* append ticket_nonce */
			ret = _gnutls_buffer_append_data_prefix(&buf, 8, ticket.nonce, ticket.nonce_size);
			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}

			/* append ticket */
			ret = _gnutls_buffer_append_data_prefix(&buf, 16, ticket.ticket.data, ticket.ticket.size);
			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}

			_gnutls_free_datum(&ticket.ticket);

			/* append extensions */
			ret = _gnutls_extv_append_init(&buf);
			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}
			init_pos = ret;

			ret = _gnutls_extv_append(&buf, ext_mod_early_data.tls_id, session,
						  (extv_append_func)append_nst_extension);
			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}

			ret = _gnutls_extv_append_final(&buf, init_pos, 0);
			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}

			bufel = _gnutls_buffer_to_mbuffer(&buf);

			ret = _gnutls_send_handshake2(session, bufel,
						      GNUTLS_HANDSHAKE_NEW_SESSION_TICKET, 1);
			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}

			session->internals.hsk_flags |= HSK_TLS13_TICKET_SENT;
		}
	}

	ret = _gnutls_handshake_io_write_flush(session);

	return ret;

cleanup:
	_gnutls_free_datum(&ticket.ticket);
	_mbuffer_xfree(&bufel);
	_gnutls_buffer_clear(&buf);

	return ret;
}
Example #17
0
static int
_gnutls_sr_send_params (gnutls_session_t session, gnutls_buffer_st* extdata)
{
  /* The format of this extension is a one-byte length of verify data followed
   * by the verify data itself. Note that the length byte does not include
   * itself; IOW, empty verify data is represented as a length of 0. That means
   * the minimum extension is one byte: 0x00.
   */
  sr_ext_st *priv;
  int ret, set = 0, len;
  extension_priv_data_t epriv;
  size_t init_length = extdata->length;

  if (session->internals.priorities.sr == SR_DISABLED)
    {
      gnutls_assert ();
      return 0;
    }

  ret = _gnutls_ext_get_session_data (session,
                                      GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
                                      &epriv);
  if (ret < 0)
    {
      set = 1;
    }

  if (set != 0)
    {
      priv = gnutls_calloc (1, sizeof (*priv));
      if (priv == NULL)
        {
          gnutls_assert ();
          return GNUTLS_E_MEMORY_ERROR;
        }
      epriv.ptr = priv;

      _gnutls_ext_set_session_data (session,
                                    GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
                                    epriv);
    }
  else
    priv = epriv.ptr;

  /* Always offer the extension if we're a client */
  if (priv->connection_using_safe_renegotiation ||
      session->security_parameters.entity == GNUTLS_CLIENT)
    {
      len = priv->client_verify_data_len;
      if (session->security_parameters.entity == GNUTLS_SERVER)
        len += priv->server_verify_data_len;
      
      ret = _gnutls_buffer_append_prefix(extdata, 8, len);
      if (ret < 0)
        return gnutls_assert_val(ret);

      ret = _gnutls_buffer_append_data(extdata, priv->client_verify_data,
        priv->client_verify_data_len);
      if (ret < 0)
        return gnutls_assert_val(ret);

      if (session->security_parameters.entity == GNUTLS_SERVER)
        {
          ret = _gnutls_buffer_append_data(extdata, priv->server_verify_data,
            priv->server_verify_data_len);
          if (ret < 0)
            return gnutls_assert_val(ret);
        }
    }
  else
    return 0;

  return extdata->length - init_length;
}