Ejemplo n.º 1
0
/* This is a temporary function to be used before the generate_*
   internal API is changed to use mbuffers. For now we don't avoid the
   extra alloc + memcpy. */
static inline int
send_handshake (gnutls_session_t session, opaque * data, size_t size,
                gnutls_handshake_description_t type)
{
  mbuffer_st *bufel;

  if (data == NULL && size == 0)
    return _gnutls_send_handshake (session, NULL, type);

  if (data == NULL && size > 0)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  bufel = _gnutls_handshake_alloc(session, size, size);
  if (bufel == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  _mbuffer_set_udata (bufel, data, size);

  return _gnutls_send_handshake (session, bufel, type);
}
Ejemplo n.º 2
0
int
_gnutls_send_server_certificate_status(gnutls_session_t session, int again)
{
	mbuffer_st *bufel = NULL;
	uint8_t *data;
	int data_size = 0;
	int ret;
	status_request_ext_st *priv = NULL;
	extension_priv_data_t epriv;
	if (again == 0) {
		ret =
		    _gnutls_ext_get_session_data(session,
						 GNUTLS_EXTENSION_STATUS_REQUEST,
						 &epriv);
		if (ret < 0)
			return 0;
		priv = epriv.ptr;

		if (!priv->response.size)
			return 0;

		data_size = priv->response.size + 4;
		bufel =
		    _gnutls_handshake_alloc(session, data_size, data_size);
		if (!bufel)
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

		data = _mbuffer_get_udata_ptr(bufel);

		data[0] = 0x01;
		_gnutls_write_uint24(priv->response.size, &data[1]);
		memcpy(&data[4], priv->response.data, priv->response.size);

		_gnutls_free_datum(&priv->response);
	}
	return _gnutls_send_handshake(session, data_size ? bufel : NULL,
				      GNUTLS_HANDSHAKE_CERTIFICATE_STATUS);
}
Ejemplo n.º 3
0
int _gnutls13_send_key_update(gnutls_session_t session, unsigned again, unsigned flags /* GNUTLS_KU_* */)
{
	int ret;
	mbuffer_st *bufel = NULL;
	uint8_t val;

	if (again == 0) {
		if (flags & GNUTLS_KU_PEER) {
			/* mark that we asked a key update to prevent an
			 * infinite ping pong when receiving the reply */
			session->internals.hsk_flags |= HSK_KEY_UPDATE_ASKED;
			val = 0x01;
		} else {
			val = 0x00;
		}

		_gnutls_handshake_log("HSK[%p]: sending key update (%u)\n", session, (unsigned)val);

		bufel = _gnutls_handshake_alloc(session, 1);
		if (bufel == NULL)
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

		_mbuffer_set_udata_size(bufel, 0);
		ret = _mbuffer_append_data(bufel, &val, 1);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

	}

	return _gnutls_send_handshake(session, bufel, GNUTLS_HANDSHAKE_KEY_UPDATE);

cleanup:
	_mbuffer_xfree(&bufel);
	return ret;
}
Ejemplo n.º 4
0
/*
 * Return zero if session tickets haven't been enabled.
 */
int _gnutls_send_new_session_ticket(gnutls_session_t session, int again)
{
	mbuffer_st *bufel = NULL;
	uint8_t *data = NULL, *p;
	int data_size = 0;
	int ret;
	gnutls_datum_t state = { NULL, 0 };
	uint16_t epoch_saved = session->security_parameters.epoch_write;
	gnutls_datum_t ticket_data;

	if (again == 0) {
		if (session->internals.flags & GNUTLS_NO_TICKETS)
			return 0;
		if (!session->internals.session_ticket_renew)
			return 0;

		_gnutls_handshake_log
		    ("HSK[%p]: sending session ticket\n", session);

		/* XXX: Temporarily set write algorithms to be used.
		   _gnutls_write_connection_state_init() does this job, but it also
		   triggers encryption, while NewSessionTicket should not be
		   encrypted in the record layer. */
		ret =
		    _gnutls_epoch_set_keys(session,
					   session->security_parameters.
					   epoch_next, 0);
		if (ret < 0) {
			gnutls_assert();
			return ret;
		}

		/* Under TLS1.2 with session tickets, the session ID is used for different
		 * purposes than the TLS1.0 session ID. Ensure that there is an internally
		 * set value which the server will see on the original and resumed sessions */
		if (session->internals.resumed != RESUME_TRUE) {
			ret = _gnutls_generate_session_id(session->security_parameters.
							  session_id,
							  &session->security_parameters.
							  session_id_size);
			if (ret < 0) {
				gnutls_assert();
				return ret;
			}
		}

		session->security_parameters.epoch_write =
		    session->security_parameters.epoch_next;

		/* Pack security parameters. */
		ret = _gnutls_session_pack(session, &state);
		if (ret < 0) {
			gnutls_assert();
			return ret;
		}

		/* Generate an encrypted ticket */
		ret = _gnutls_encrypt_session_ticket(session, &state, &ticket_data);
		session->security_parameters.epoch_write = epoch_saved;
		_gnutls_free_datum(&state);
		if (ret < 0) {
			gnutls_assert();
			return ret;
		}

		bufel =
		    _gnutls_handshake_alloc(session, 
					    4 + 2 + ticket_data.size);
		if (!bufel) {
			gnutls_assert();
			_gnutls_free_datum(&ticket_data);
			return GNUTLS_E_MEMORY_ERROR;
		}

		data = _mbuffer_get_udata_ptr(bufel);
		p = data;

		_gnutls_write_uint32(session->internals.expire_time, p);
		p += 4;

		_gnutls_write_uint16(ticket_data.size, p);
		p += 2;

		memcpy(p, ticket_data.data, ticket_data.size);
		p += ticket_data.size;

		_gnutls_free_datum(&ticket_data);

		data_size = p - data;

		session->internals.hsk_flags |= HSK_TLS12_TICKET_SENT;
	}
	return _gnutls_send_handshake(session, data_size ? bufel : NULL,
				      GNUTLS_HANDSHAKE_NEW_SESSION_TICKET);
}
Ejemplo n.º 5
0
int _gnutls_send_new_session_ticket(gnutls_session_t session, int again)
{
    mbuffer_st *bufel = NULL;
    uint8_t *data = NULL, *p;
    int data_size = 0;
    int ret;
    struct ticket_st ticket;
    uint16_t ticket_len;
    session_ticket_ext_st *priv = NULL;
    extension_priv_data_t epriv;
    uint16_t epoch_saved = session->security_parameters.epoch_write;

    if (again == 0) {
        ret =
            _gnutls_ext_get_session_data(session,
                                         GNUTLS_EXTENSION_SESSION_TICKET,
                                         &epriv);
        if (ret < 0)
            return 0;
        priv = epriv;

        if (!priv->session_ticket_renew)
            return 0;

        /* XXX: Temporarily set write algorithms to be used.
           _gnutls_write_connection_state_init() does this job, but it also
           triggers encryption, while NewSessionTicket should not be
           encrypted in the record layer. */
        ret =
            _gnutls_epoch_set_keys(session,
                                   session->security_parameters.
                                   epoch_next);
        if (ret < 0) {
            gnutls_assert();
            return ret;
        }

        session->security_parameters.epoch_write =
            session->security_parameters.epoch_next;

        ret = encrypt_ticket(session, priv, &ticket);
        session->security_parameters.epoch_write = epoch_saved;
        if (ret < 0) {
            gnutls_assert();
            return ret;
        }

        ticket_len =
            KEY_NAME_SIZE + IV_SIZE + 2 +
            ticket.encrypted_state_len + MAC_SIZE;

        bufel =
            _gnutls_handshake_alloc(session,
                                    4 + 2 + ticket_len);
        if (!bufel) {
            gnutls_assert();
            gnutls_free(ticket.encrypted_state);
            return GNUTLS_E_MEMORY_ERROR;
        }

        data = _mbuffer_get_udata_ptr(bufel);
        p = data;

        _gnutls_write_uint32(session->internals.expire_time, p);
        p += 4;

        _gnutls_write_uint16(ticket_len, p);
        p += 2;

        memcpy(p, ticket.key_name, KEY_NAME_SIZE);
        p += KEY_NAME_SIZE;

        memcpy(p, ticket.IV, IV_SIZE);
        p += IV_SIZE;

        _gnutls_write_uint16(ticket.encrypted_state_len, p);
        p += 2;

        memcpy(p, ticket.encrypted_state, ticket.encrypted_state_len);
        gnutls_free(ticket.encrypted_state);
        p += ticket.encrypted_state_len;

        memcpy(p, ticket.mac, MAC_SIZE);
        p += MAC_SIZE;

        data_size = p - data;

        session->internals.ticket_sent = 1;
    }
    return _gnutls_send_handshake(session, data_size ? bufel : NULL,
                                  GNUTLS_HANDSHAKE_NEW_SESSION_TICKET);
}