Blame lib/record.c

Packit aea12f
/*
Packit aea12f
 * Copyright (C) 2000-2018 Free Software Foundation, Inc.
Packit aea12f
 * Copyright (C) 2012-2018 Nikos Mavrogiannopoulos
Packit aea12f
 * Copyright (C) 2018 Red Hat, Inc.
Packit aea12f
 *
Packit aea12f
 * Author: Nikos Mavrogiannopoulos
Packit aea12f
 *
Packit aea12f
 * This file is part of GnuTLS.
Packit aea12f
 *
Packit aea12f
 * The GnuTLS is free software; you can redistribute it and/or
Packit aea12f
 * modify it under the terms of the GNU Lesser General Public License
Packit aea12f
 * as published by the Free Software Foundation; either version 2.1 of
Packit aea12f
 * the License, or (at your option) any later version.
Packit aea12f
 *
Packit aea12f
 * This library is distributed in the hope that it will be useful, but
Packit aea12f
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit aea12f
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit aea12f
 * Lesser General Public License for more details.
Packit aea12f
 *
Packit aea12f
 * You should have received a copy of the GNU Lesser General Public License
Packit aea12f
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
Packit aea12f
 *
Packit aea12f
 */
Packit aea12f
Packit aea12f
/* Functions that are record layer specific, are included in this file.
Packit aea12f
 */
Packit aea12f
Packit aea12f
/* allocate this many bytes more when encrypting or decrypting, to
Packit aea12f
 * compensate for broken backends such as cryptodev.
Packit aea12f
 */
Packit aea12f
#define CIPHER_SLACK_SIZE 32
Packit aea12f
Packit aea12f
#include "gnutls_int.h"
Packit aea12f
#include "errors.h"
Packit aea12f
#include "debug.h"
Packit aea12f
#include "cipher.h"
Packit aea12f
#include "buffers.h"
Packit aea12f
#include "mbuffers.h"
Packit aea12f
#include "handshake.h"
Packit aea12f
#include "hash_int.h"
Packit aea12f
#include "cipher_int.h"
Packit aea12f
#include "algorithms.h"
Packit aea12f
#include "db.h"
Packit aea12f
#include "auth.h"
Packit aea12f
#include "num.h"
Packit aea12f
#include "record.h"
Packit aea12f
#include "datum.h"
Packit aea12f
#include "constate.h"
Packit aea12f
#include "tls13/key_update.h"
Packit aea12f
#include <ext/heartbeat.h>
Packit aea12f
#include <state.h>
Packit aea12f
#include <dtls.h>
Packit aea12f
#include <dh.h>
Packit aea12f
#include <random.h>
Packit aea12f
#include <xsize.h>
Packit aea12f
#include "locks.h"
Packit aea12f
Packit aea12f
struct tls_record_st {
Packit aea12f
	uint16_t header_size;
Packit aea12f
	uint8_t version[2];
Packit Service 991b93
	uint64_t sequence;	/* DTLS */
Packit aea12f
	uint16_t length;
Packit aea12f
	uint16_t packet_size;	/* header_size + length */
Packit aea12f
	content_type_t type;
Packit aea12f
	uint16_t epoch;		/* valid in DTLS only */
Packit aea12f
#ifdef ENABLE_SSL2
Packit aea12f
	unsigned v2:1;		/* whether an SSLv2 client hello */
Packit aea12f
#endif
Packit aea12f
	/* the data */
Packit aea12f
};
Packit aea12f
Packit aea12f
/**
Packit Service 991b93
 * gnutls_record_disable_padding:
Packit aea12f
 * @session: is a #gnutls_session_t type.
Packit aea12f
 *
Packit aea12f
 * Used to disabled padding in TLS 1.0 and above.  Normally you do not
Packit aea12f
 * need to use this function, but there are buggy clients that
Packit aea12f
 * complain if a server pads the encrypted data.  This of course will
Packit aea12f
 * disable protection against statistical attacks on the data.
Packit aea12f
 *
Packit aea12f
 * This function is defunct since 3.1.7. Random padding is disabled
Packit aea12f
 * by default unless requested using gnutls_record_send_range().
Packit aea12f
 *
Packit aea12f
 **/
Packit aea12f
void gnutls_record_disable_padding(gnutls_session_t session)
Packit aea12f
{
Packit aea12f
	return;
Packit aea12f
}
Packit aea12f
Packit aea12f
/**
Packit aea12f
 * gnutls_transport_set_ptr:
Packit aea12f
 * @session: is a #gnutls_session_t type.
Packit aea12f
 * @ptr: is the value.
Packit aea12f
 *
Packit aea12f
 * Used to set the first argument of the transport function (for push
Packit aea12f
 * and pull callbacks). In berkeley style sockets this function will set the
Packit aea12f
 * connection descriptor.
Packit Service 991b93
 *
Packit aea12f
 **/
Packit aea12f
void
Packit aea12f
gnutls_transport_set_ptr(gnutls_session_t session,
Packit aea12f
			 gnutls_transport_ptr_t ptr)
Packit aea12f
{
Packit aea12f
	session->internals.transport_recv_ptr = ptr;
Packit aea12f
	session->internals.transport_send_ptr = ptr;
Packit aea12f
}
Packit aea12f
Packit aea12f
/**
Packit aea12f
 * gnutls_transport_set_ptr2:
Packit aea12f
 * @session: is a #gnutls_session_t type.
Packit aea12f
 * @recv_ptr: is the value for the pull function
Packit aea12f
 * @send_ptr: is the value for the push function
Packit aea12f
 *
Packit aea12f
 * Used to set the first argument of the transport function (for push
Packit aea12f
 * and pull callbacks). In berkeley style sockets this function will set the
Packit aea12f
 * connection descriptor.  With this function you can use two different
Packit aea12f
 * pointers for receiving and sending.
Packit aea12f
 **/
Packit aea12f
void
Packit aea12f
gnutls_transport_set_ptr2(gnutls_session_t session,
Packit aea12f
			  gnutls_transport_ptr_t recv_ptr,
Packit aea12f
			  gnutls_transport_ptr_t send_ptr)
Packit aea12f
{
Packit aea12f
	session->internals.transport_send_ptr = send_ptr;
Packit aea12f
	session->internals.transport_recv_ptr = recv_ptr;
Packit aea12f
}
Packit aea12f
Packit aea12f
/**
Packit aea12f
 * gnutls_transport_set_int2:
Packit aea12f
 * @session: is a #gnutls_session_t type.
Packit aea12f
 * @recv_fd: is socket descriptor for the pull function
Packit aea12f
 * @send_fd: is socket descriptor for the push function
Packit aea12f
 *
Packit aea12f
 * This function sets the first argument of the transport functions,
Packit aea12f
 * such as send() and recv() for the default callbacks using the
Packit aea12f
 * system's socket API. With this function you can set two different
Packit aea12f
 * descriptors for receiving and sending.
Packit aea12f
 *
Packit aea12f
 * This function is equivalent to calling gnutls_transport_set_ptr2()
Packit aea12f
 * with the descriptors, but requires no casts.
Packit aea12f
 *
Packit aea12f
 * Since: 3.1.9
Packit aea12f
 **/
Packit aea12f
void
Packit aea12f
gnutls_transport_set_int2(gnutls_session_t session,
Packit aea12f
			  int recv_fd, int send_fd)
Packit aea12f
{
Packit aea12f
	session->internals.transport_send_ptr =
Packit aea12f
	    (gnutls_transport_ptr_t) (long) send_fd;
Packit aea12f
	session->internals.transport_recv_ptr =
Packit aea12f
	    (gnutls_transport_ptr_t) (long) recv_fd;
Packit aea12f
}
Packit aea12f
Packit aea12f
#if 0
Packit aea12f
/* this will be a macro */
Packit aea12f
/**
Packit aea12f
 * gnutls_transport_set_int:
Packit aea12f
 * @session: is a #gnutls_session_t type.
Packit aea12f
 * @fd: is the socket descriptor for the connection.
Packit aea12f
 *
Packit aea12f
 * This function sets the first argument of the transport function, such
Packit aea12f
 * as send() and recv() for the default callbacks using the
Packit aea12f
 * system's socket API.
Packit aea12f
 *
Packit aea12f
 * This function is equivalent to calling gnutls_transport_set_ptr()
Packit aea12f
 * with the descriptor, but requires no casts.
Packit aea12f
 *
Packit aea12f
 * Since: 3.1.9
Packit Service 991b93
 *
Packit aea12f
 **/
Packit aea12f
void gnutls_transport_set_int(gnutls_session_t session, int fd)
Packit aea12f
{
Packit aea12f
	session->internals.transport_recv_ptr =
Packit aea12f
	    (gnutls_transport_ptr_t) (long) fd;
Packit aea12f
	session->internals.transport_send_ptr =
Packit aea12f
	    (gnutls_transport_ptr_t) (long) fd;
Packit aea12f
}
Packit aea12f
#endif
Packit aea12f
Packit aea12f
/**
Packit aea12f
 * gnutls_transport_get_ptr:
Packit aea12f
 * @session: is a #gnutls_session_t type.
Packit aea12f
 *
Packit aea12f
 * Used to get the first argument of the transport function (like
Packit aea12f
 * PUSH and PULL).  This must have been set using
Packit aea12f
 * gnutls_transport_set_ptr().
Packit aea12f
 *
Packit aea12f
 * Returns: The first argument of the transport function.
Packit aea12f
 **/
Packit aea12f
gnutls_transport_ptr_t gnutls_transport_get_ptr(gnutls_session_t session)
Packit aea12f
{
Packit aea12f
	return session->internals.transport_recv_ptr;
Packit aea12f
}
Packit aea12f
Packit aea12f
/**
Packit aea12f
 * gnutls_transport_get_ptr2:
Packit aea12f
 * @session: is a #gnutls_session_t type.
Packit aea12f
 * @recv_ptr: will hold the value for the pull function
Packit aea12f
 * @send_ptr: will hold the value for the push function
Packit aea12f
 *
Packit aea12f
 * Used to get the arguments of the transport functions (like PUSH
Packit aea12f
 * and PULL).  These should have been set using
Packit aea12f
 * gnutls_transport_set_ptr2().
Packit aea12f
 **/
Packit aea12f
void
Packit aea12f
gnutls_transport_get_ptr2(gnutls_session_t session,
Packit aea12f
			  gnutls_transport_ptr_t * recv_ptr,
Packit aea12f
			  gnutls_transport_ptr_t * send_ptr)
Packit aea12f
{
Packit aea12f
Packit aea12f
	*recv_ptr = session->internals.transport_recv_ptr;
Packit aea12f
	*send_ptr = session->internals.transport_send_ptr;
Packit aea12f
}
Packit aea12f
Packit aea12f
/**
Packit aea12f
 * gnutls_transport_get_int2:
Packit aea12f
 * @session: is a #gnutls_session_t type.
Packit aea12f
 * @recv_int: will hold the value for the pull function
Packit aea12f
 * @send_int: will hold the value for the push function
Packit aea12f
 *
Packit aea12f
 * Used to get the arguments of the transport functions (like PUSH
Packit aea12f
 * and PULL).  These should have been set using
Packit aea12f
 * gnutls_transport_set_int2().
Packit aea12f
 *
Packit aea12f
 * Since: 3.1.9
Packit aea12f
 **/
Packit aea12f
void
Packit aea12f
gnutls_transport_get_int2(gnutls_session_t session,
Packit aea12f
			  int *recv_int, int *send_int)
Packit aea12f
{
Packit aea12f
Packit aea12f
	*recv_int = (long) session->internals.transport_recv_ptr;
Packit aea12f
	*send_int = (long) session->internals.transport_send_ptr;
Packit aea12f
}
Packit aea12f
Packit aea12f
/**
Packit aea12f
 * gnutls_transport_get_int:
Packit aea12f
 * @session: is a #gnutls_session_t type.
Packit aea12f
 *
Packit aea12f
 * Used to get the first argument of the transport function (like
Packit aea12f
 * PUSH and PULL).  This must have been set using
Packit aea12f
 * gnutls_transport_set_int().
Packit aea12f
 *
Packit aea12f
 * Returns: The first argument of the transport function.
Packit aea12f
 *
Packit aea12f
 * Since: 3.1.9
Packit aea12f
 **/
Packit aea12f
int gnutls_transport_get_int(gnutls_session_t session)
Packit aea12f
{
Packit aea12f
	return (long) session->internals.transport_recv_ptr;
Packit aea12f
}
Packit aea12f
Packit aea12f
/**
Packit aea12f
 * gnutls_bye:
Packit aea12f
 * @session: is a #gnutls_session_t type.
Packit aea12f
 * @how: is an integer
Packit aea12f
 *
Packit aea12f
 * Terminates the current TLS/SSL connection. The connection should
Packit aea12f
 * have been initiated using gnutls_handshake().  @how should be one
Packit aea12f
 * of %GNUTLS_SHUT_RDWR, %GNUTLS_SHUT_WR.
Packit aea12f
 *
Packit aea12f
 * In case of %GNUTLS_SHUT_RDWR the TLS session gets
Packit aea12f
 * terminated and further receives and sends will be disallowed.  If
Packit aea12f
 * the return value is zero you may continue using the underlying
Packit aea12f
 * transport layer. %GNUTLS_SHUT_RDWR sends an alert containing a close
Packit aea12f
 * request and waits for the peer to reply with the same message.
Packit aea12f
 *
Packit aea12f
 * In case of %GNUTLS_SHUT_WR the TLS session gets terminated
Packit aea12f
 * and further sends will be disallowed. In order to reuse the
Packit aea12f
 * connection you should wait for an EOF from the peer.
Packit aea12f
 * %GNUTLS_SHUT_WR sends an alert containing a close request.
Packit aea12f
 *
Packit aea12f
 * Note that not all implementations will properly terminate a TLS
Packit aea12f
 * connection.  Some of them, usually for performance reasons, will
Packit aea12f
 * terminate only the underlying transport layer, and thus not
Packit Service 991b93
 * distinguishing between a malicious party prematurely terminating
Packit Service 991b93
 * the connection and normal termination.
Packit aea12f
 *
Packit aea12f
 * This function may also return %GNUTLS_E_AGAIN or
Packit aea12f
 * %GNUTLS_E_INTERRUPTED; cf.  gnutls_record_get_direction().
Packit aea12f
 *
Packit aea12f
 * Returns: %GNUTLS_E_SUCCESS on success, or an error code, see
Packit aea12f
 *   function documentation for entire semantics.
Packit aea12f
 **/
Packit aea12f
int gnutls_bye(gnutls_session_t session, gnutls_close_request_t how)
Packit aea12f
{
Packit aea12f
	int ret = 0;
Packit aea12f
Packit aea12f
	switch (BYE_STATE) {
Packit aea12f
	case BYE_STATE0:
Packit aea12f
		ret = _gnutls_io_write_flush(session);
Packit aea12f
		BYE_STATE = BYE_STATE0;
Packit aea12f
		if (ret < 0) {
Packit aea12f
			gnutls_assert();
Packit aea12f
			return ret;
Packit aea12f
		}
Packit aea12f
		FALLTHROUGH;
Packit aea12f
	case BYE_STATE1:
Packit aea12f
		ret =
Packit aea12f
		    gnutls_alert_send(session, GNUTLS_AL_WARNING,
Packit aea12f
				      GNUTLS_A_CLOSE_NOTIFY);
Packit aea12f
		BYE_STATE = BYE_STATE1;
Packit aea12f
		if (ret < 0) {
Packit aea12f
			gnutls_assert();
Packit aea12f
			return ret;
Packit aea12f
		}
Packit aea12f
		FALLTHROUGH;
Packit aea12f
	case BYE_STATE2:
Packit aea12f
		BYE_STATE = BYE_STATE2;
Packit aea12f
		if (how == GNUTLS_SHUT_RDWR) {
Packit aea12f
			do {
Packit aea12f
				ret =
Packit aea12f
				    _gnutls_recv_int(session, GNUTLS_ALERT,
Packit aea12f
						     NULL, 0, NULL,
Packit aea12f
						     session->internals.
Packit aea12f
						     record_timeout_ms);
Packit aea12f
			}
Packit aea12f
			while (ret == GNUTLS_E_GOT_APPLICATION_DATA);
Packit aea12f
Packit aea12f
			if (ret >= 0)
Packit aea12f
				session->internals.may_not_read = 1;
Packit aea12f
Packit aea12f
			if (ret < 0) {
Packit aea12f
				gnutls_assert();
Packit aea12f
				return ret;
Packit aea12f
			}
Packit aea12f
		}
Packit aea12f
		BYE_STATE = BYE_STATE2;
Packit aea12f
Packit aea12f
		break;
Packit aea12f
	default:
Packit aea12f
		gnutls_assert();
Packit aea12f
		return GNUTLS_E_INTERNAL_ERROR;
Packit aea12f
	}
Packit aea12f
Packit aea12f
	BYE_STATE = BYE_STATE0;
Packit aea12f
Packit aea12f
	session->internals.may_not_write = 1;
Packit aea12f
	return 0;
Packit aea12f
}
Packit aea12f
Packit aea12f
inline static void session_unresumable(gnutls_session_t session)
Packit aea12f
{
Packit aea12f
	session->internals.resumable = RESUME_FALSE;
Packit aea12f
}
Packit aea12f
Packit aea12f
/* returns 0 if session is valid
Packit aea12f
 */
Packit aea12f
inline static int session_is_valid(gnutls_session_t session)
Packit aea12f
{
Packit aea12f
	if (session->internals.invalid_connection != 0)
Packit aea12f
		return GNUTLS_E_INVALID_SESSION;
Packit aea12f
Packit aea12f
	return 0;
Packit aea12f
}
Packit aea12f
Packit Service 991b93
/* Copies the record version into the headers. The
Packit aea12f
 * version must have 2 bytes at least.
Packit aea12f
 */
Packit aea12f
inline static int
Packit aea12f
copy_record_version(gnutls_session_t session,
Packit aea12f
		    gnutls_handshake_description_t htype,
Packit aea12f
		    uint8_t version[2])
Packit aea12f
{
Packit aea12f
	const version_entry_st *lver;
Packit aea12f
Packit aea12f
	lver = get_version(session);
Packit aea12f
	if (session->internals.initial_negotiation_completed ||
Packit aea12f
	    htype != GNUTLS_HANDSHAKE_CLIENT_HELLO ||
Packit aea12f
	    session->internals.default_record_version[0] == 0) {
Packit aea12f
Packit aea12f
		if (unlikely(lver == NULL))
Packit aea12f
			return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit aea12f
Packit aea12f
		if (lver->tls13_sem) {
Packit aea12f
			version[0] = 0x03;
Packit aea12f
			version[1] = 0x03;
Packit aea12f
		} else {
Packit aea12f
			version[0] = lver->major;
Packit aea12f
			version[1] = lver->minor;
Packit aea12f
		}
Packit aea12f
	} else {
Packit aea12f
		version[0] = session->internals.default_record_version[0];
Packit aea12f
		version[1] = session->internals.default_record_version[1];
Packit aea12f
	}
Packit aea12f
Packit aea12f
	return 0;
Packit aea12f
}
Packit aea12f
Packit aea12f
/* Increments the sequence value
Packit aea12f
 */
Packit aea12f
inline static int
Packit Service 991b93
sequence_increment(gnutls_session_t session, uint64_t * value)
Packit aea12f
{
Packit Service 991b93
	uint64_t snmax = UINT64_C(0xffffffffffffffff);
Packit Service 991b93
Packit aea12f
	if (IS_DTLS(session)) {
Packit Service 991b93
		uint64_t mask;
Packit Service 991b93
Packit Service 991b93
		snmax = UINT64_C(0xffffffffffff);
Packit Service 991b93
		mask = snmax;
Packit Service 991b93
Packit Service 991b93
		if ((*value & mask) == snmax)
Packit Service 991b93
			return -1;
Packit Service 991b93
Packit Service 991b93
		*value = ((*value & mask) + 1) | (*value & ~mask);
Packit aea12f
	} else {
Packit Service 991b93
		if (*value == snmax)
Packit Service 991b93
			return -1;
Packit Service 991b93
Packit Service 991b93
		(*value)++;
Packit aea12f
	}
Packit Service 991b93
Packit Service 991b93
	return 0;
Packit aea12f
}
Packit aea12f
Packit aea12f
/* This function behaves exactly like write(). The only difference is
Packit aea12f
 * that it accepts, the gnutls_session_t and the content_type_t of data to
Packit aea12f
 * send (if called by the user the Content is specific)
Packit Service 991b93
 * It is intended to transfer data, under the current session.
Packit aea12f
 *
Packit aea12f
 * @type: The content type to send
Packit aea12f
 * @htype: If this is a handshake message then the handshake type
Packit aea12f
 * @epoch_rel: %EPOCH_READ_* or %EPOCH_WRITE_*
Packit aea12f
 * @data: the data to be sent
Packit aea12f
 * @data_size: the size of the @data
Packit aea12f
 * @min_pad: the minimum required padding
Packit aea12f
 * @mflags: zero or %MBUFFER_FLUSH
Packit aea12f
 *
Packit aea12f
 * Oct 30 2001: Removed capability to send data more than MAX_RECORD_SIZE.
Packit aea12f
 * This makes the function much easier to read, and more error resistant
Packit aea12f
 * (there were cases were the old function could mess everything up).
Packit aea12f
 * --nmav
Packit aea12f
 *
Packit aea12f
 * This function may accept a NULL pointer for data, and 0 for size, if
Packit aea12f
 * and only if the previous send was interrupted for some reason.
Packit aea12f
 *
Packit aea12f
 */
Packit aea12f
ssize_t
Packit aea12f
_gnutls_send_tlen_int(gnutls_session_t session, content_type_t type,
Packit aea12f
		      gnutls_handshake_description_t htype,
Packit aea12f
		      unsigned int epoch_rel, const void *_data,
Packit aea12f
		      size_t data_size, size_t min_pad,
Packit aea12f
		      unsigned int mflags)
Packit aea12f
{
Packit aea12f
	mbuffer_st *bufel;
Packit aea12f
	ssize_t cipher_size;
Packit aea12f
	int retval, ret;
Packit aea12f
	int send_data_size;
Packit aea12f
	uint8_t *headers;
Packit aea12f
	int header_size;
Packit aea12f
	const uint8_t *data = _data;
Packit aea12f
	record_parameters_st *record_params;
Packit aea12f
	size_t max_send_size;
Packit aea12f
	record_state_st *record_state;
Packit aea12f
	const version_entry_st *vers = get_version(session);
Packit aea12f
Packit aea12f
	ret = _gnutls_epoch_get(session, epoch_rel, &record_params);
Packit aea12f
	if (ret < 0)
Packit aea12f
		return gnutls_assert_val(ret);
Packit aea12f
Packit aea12f
	/* Safeguard against processing data with an incomplete cipher state. */
Packit aea12f
	if (!record_params->initialized)
Packit aea12f
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit aea12f
Packit aea12f
	record_state = &record_params->write;
Packit aea12f
Packit aea12f
	/* Do not allow null pointer if the send buffer is empty.
Packit aea12f
	 * If the previous send was interrupted then a null pointer is
Packit aea12f
	 * ok, and means to resume.
Packit aea12f
	 */
Packit aea12f
	if (session->internals.record_send_buffer.byte_length == 0 &&
Packit aea12f
	    (data_size == 0 && _data == NULL)) {
Packit aea12f
		gnutls_assert();
Packit aea12f
		return GNUTLS_E_INVALID_REQUEST;
Packit aea12f
	}
Packit aea12f
Packit aea12f
	if (type != GNUTLS_ALERT)	/* alert messages are sent anyway */
Packit aea12f
		if (session_is_valid(session)
Packit aea12f
		    || session->internals.may_not_write != 0) {
Packit aea12f
			gnutls_assert();
Packit aea12f
			return GNUTLS_E_INVALID_SESSION;
Packit aea12f
		}
Packit aea12f
Packit aea12f
	max_send_size = max_record_send_size(session, record_params);
Packit aea12f
Packit aea12f
	if (data_size > max_send_size) {
Packit aea12f
		if (IS_DTLS(session))
Packit aea12f
			return gnutls_assert_val(GNUTLS_E_LARGE_PACKET);
Packit aea12f
Packit aea12f
		send_data_size = max_send_size;
Packit aea12f
	} else
Packit aea12f
		send_data_size = data_size;
Packit aea12f
Packit Service 991b93
	/* Only encrypt if we don't have data to send
Packit aea12f
	 * from the previous run. - probably interrupted.
Packit aea12f
	 */
Packit aea12f
	if (mflags != 0
Packit aea12f
	    && session->internals.record_send_buffer.byte_length > 0) {
Packit aea12f
		ret = _gnutls_io_write_flush(session);
Packit aea12f
		if (ret > 0)
Packit aea12f
			cipher_size = ret;
Packit aea12f
		else
Packit aea12f
			cipher_size = 0;
Packit aea12f
Packit aea12f
		retval = session->internals.record_send_buffer_user_size;
Packit aea12f
	} else {
Packit aea12f
		if (unlikely((send_data_size == 0 && min_pad == 0)))
Packit aea12f
			return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit aea12f
Packit aea12f
		/* now proceed to packet encryption
Packit aea12f
		 */
Packit aea12f
		cipher_size = MAX_RECORD_SEND_SIZE(session);
Packit aea12f
Packit Service 991b93
		bufel = _mbuffer_alloc_align16(cipher_size + CIPHER_SLACK_SIZE,
Packit aea12f
			get_total_headers2(session, record_params));
Packit aea12f
		if (bufel == NULL)
Packit aea12f
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
Packit aea12f
Packit aea12f
		headers = _mbuffer_get_uhead_ptr(bufel);
Packit aea12f
		if (vers->tls13_sem && record_params->cipher->id != GNUTLS_CIPHER_NULL)
Packit aea12f
			headers[0] = GNUTLS_APPLICATION_DATA;
Packit aea12f
		else
Packit aea12f
			headers[0] = type;
Packit aea12f
Packit aea12f
		/* Use the default record version, if it is
Packit aea12f
		 * set. */
Packit aea12f
		ret = copy_record_version(session, htype, &headers[1]);
Packit aea12f
		if (ret < 0)
Packit aea12f
			return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit aea12f
Packit aea12f
		/* Adjust header length and add sequence for DTLS */
Packit aea12f
		if (IS_DTLS(session))
Packit Service 991b93
			_gnutls_write_uint64(record_state->sequence_number, &headers[3]);
Packit aea12f
Packit aea12f
		_gnutls_record_log
Packit aea12f
		    ("REC[%p]: Preparing Packet %s(%d) with length: %d and min pad: %d\n",
Packit aea12f
		     session, _gnutls_packet2str(type), type,
Packit aea12f
		     (int) data_size, (int) min_pad);
Packit aea12f
Packit aea12f
		header_size = RECORD_HEADER_SIZE(session);
Packit aea12f
		_mbuffer_set_udata_size(bufel, cipher_size);
Packit aea12f
		_mbuffer_set_uhead_size(bufel, header_size);
Packit aea12f
Packit aea12f
		ret =
Packit aea12f
		    _gnutls_encrypt(session,
Packit aea12f
				    data, send_data_size, min_pad,
Packit aea12f
				    bufel, type, record_params);
Packit aea12f
		if (ret <= 0) {
Packit aea12f
			gnutls_assert();
Packit aea12f
			if (ret == 0)
Packit aea12f
				ret = GNUTLS_E_ENCRYPTION_FAILED;
Packit aea12f
			gnutls_free(bufel);
Packit aea12f
			return ret;	/* error */
Packit aea12f
		}
Packit aea12f
Packit aea12f
		cipher_size = _mbuffer_get_udata_size(bufel);
Packit aea12f
		retval = send_data_size;
Packit aea12f
		session->internals.record_send_buffer_user_size =
Packit aea12f
		    send_data_size;
Packit aea12f
Packit aea12f
		/* increase sequence number
Packit aea12f
		 */
Packit aea12f
		if (sequence_increment
Packit aea12f
		    (session, &record_state->sequence_number) != 0) {
Packit aea12f
			session_invalidate(session);
Packit aea12f
			gnutls_free(bufel);
Packit aea12f
			return
Packit aea12f
			    gnutls_assert_val
Packit aea12f
			    (GNUTLS_E_RECORD_LIMIT_REACHED);
Packit aea12f
		}
Packit aea12f
Packit aea12f
		ret = _gnutls_io_write_buffered(session, bufel, mflags);
Packit aea12f
	}
Packit aea12f
Packit aea12f
	if (ret != cipher_size) {
Packit aea12f
		/* If we have sent any data then just return
Packit aea12f
		 * the error value. Do not invalidate the session.
Packit aea12f
		 */
Packit aea12f
		if (ret < 0 && gnutls_error_is_fatal(ret) == 0)
Packit aea12f
			return gnutls_assert_val(ret);
Packit aea12f
Packit aea12f
		if (ret > 0)
Packit aea12f
			ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit aea12f
Packit aea12f
		session_unresumable(session);
Packit aea12f
		session->internals.may_not_write = 1;
Packit aea12f
		return gnutls_assert_val(ret);
Packit aea12f
	}
Packit aea12f
Packit aea12f
	session->internals.record_send_buffer_user_size = 0;
Packit aea12f
Packit aea12f
	_gnutls_record_log
Packit Service 991b93
	    ("REC[%p]: Sent Packet[%ld] %s(%d) in epoch %d and length: %d\n",
Packit Service 991b93
	     session, (unsigned long)(record_state->sequence_number),
Packit aea12f
	     _gnutls_packet2str(type), type, (int) record_params->epoch,
Packit aea12f
	     (int) cipher_size);
Packit aea12f
Packit aea12f
	if (vers->tls13_sem && !(session->internals.flags & GNUTLS_NO_AUTO_REKEY) &&
Packit Service 991b93
	    !(record_params->cipher->flags & GNUTLS_CIPHER_FLAG_NO_REKEY)) {
Packit Service 991b93
		if (unlikely((record_state->sequence_number & UINT64_C(0xffffff)) == UINT64_C(0xfffffd))) {
Packit aea12f
			/* After we have sent 2^24 messages, mark the session
Packit aea12f
			 * as needing a key update. */
Packit aea12f
			session->internals.rsend_state = RECORD_SEND_KEY_UPDATE_1;
Packit aea12f
		}
Packit aea12f
	}
Packit aea12f
Packit aea12f
	return retval;
Packit aea12f
}
Packit aea12f
Packit aea12f
inline static int
Packit aea12f
check_recv_type(gnutls_session_t session, content_type_t recv_type)
Packit aea12f
{
Packit aea12f
	switch (recv_type) {
Packit aea12f
	case GNUTLS_CHANGE_CIPHER_SPEC:
Packit aea12f
	case GNUTLS_ALERT:
Packit aea12f
	case GNUTLS_HANDSHAKE:
Packit aea12f
	case GNUTLS_HEARTBEAT:
Packit aea12f
	case GNUTLS_APPLICATION_DATA:
Packit aea12f
		return 0;
Packit aea12f
	default:
Packit aea12f
		gnutls_assert();
Packit aea12f
		_gnutls_audit_log(session,
Packit aea12f
				  "Received record packet of unknown type %u\n",
Packit aea12f
				  (unsigned int) recv_type);
Packit aea12f
		return GNUTLS_E_UNEXPECTED_PACKET;
Packit aea12f
	}
Packit aea12f
Packit aea12f
}
Packit aea12f
Packit aea12f
Packit aea12f
/* Checks if there are pending data in the record buffers. If there are
Packit aea12f
 * then it copies the data.
Packit aea12f
 */
Packit aea12f
static int
Packit aea12f
get_data_from_buffers(gnutls_session_t session, content_type_t type,
Packit aea12f
	      uint8_t * data, int data_size, void *seq)
Packit aea12f
{
Packit aea12f
	if ((type == GNUTLS_APPLICATION_DATA ||
Packit aea12f
	     type == GNUTLS_HANDSHAKE || type == GNUTLS_CHANGE_CIPHER_SPEC)
Packit aea12f
	    && _gnutls_record_buffer_get_size(session) > 0) {
Packit aea12f
		int ret;
Packit aea12f
		ret =
Packit aea12f
		    _gnutls_record_buffer_get(type, session, data,
Packit aea12f
					      data_size, seq);
Packit aea12f
		if (ret < 0) {
Packit aea12f
			if (IS_DTLS(session)) {
Packit aea12f
				if (ret == GNUTLS_E_UNEXPECTED_PACKET) {
Packit aea12f
					ret = GNUTLS_E_AGAIN;
Packit aea12f
				}
Packit aea12f
			}
Packit aea12f
			gnutls_assert();
Packit aea12f
			return ret;
Packit aea12f
		}
Packit aea12f
Packit aea12f
		return ret;
Packit aea12f
	}
Packit aea12f
Packit aea12f
	return 0;
Packit aea12f
}
Packit aea12f
Packit aea12f
/* Checks and retrieves any pending data in the application data record buffers.
Packit aea12f
 */
Packit aea12f
static int
Packit aea12f
get_packet_from_buffers(gnutls_session_t session, content_type_t type,
Packit aea12f
		     gnutls_packet_t *packet)
Packit aea12f
{
Packit aea12f
	if (_gnutls_record_buffer_get_size(session) > 0) {
Packit aea12f
		int ret;
Packit aea12f
		ret =
Packit aea12f
			_gnutls_record_buffer_get_packet(type, session, packet);
Packit aea12f
		if (ret < 0) {
Packit aea12f
			if (IS_DTLS(session)) {
Packit aea12f
				if (ret == GNUTLS_E_UNEXPECTED_PACKET) {
Packit aea12f
					ret = GNUTLS_E_AGAIN;
Packit aea12f
				}
Packit aea12f
			}
Packit aea12f
			gnutls_assert();
Packit aea12f
			return ret;
Packit aea12f
		}
Packit aea12f
Packit aea12f
		return ret;
Packit aea12f
	}
Packit aea12f
Packit aea12f
	*packet = NULL;
Packit aea12f
	return 0;
Packit aea12f
}
Packit aea12f
Packit aea12f
Packit aea12f
Packit aea12f
/* Here we check if the advertized version is the one we
Packit aea12f
 * negotiated in the handshake.
Packit aea12f
 */
Packit aea12f
inline static int
Packit aea12f
record_check_version(gnutls_session_t session,
Packit aea12f
		     gnutls_handshake_description_t htype,
Packit aea12f
		     uint8_t version[2])
Packit aea12f
{
Packit aea12f
	const version_entry_st *vers = get_version(session);
Packit aea12f
	int diff = 0;
Packit aea12f
Packit aea12f
	if (vers->tls13_sem) {
Packit aea12f
		/* TLS 1.3 requires version to be 0x0303 */
Packit aea12f
		if (version[0] != 0x03 || version[1] != 0x03)
Packit aea12f
			diff = 1;
Packit aea12f
	} else {
Packit aea12f
		if (vers->major != version[0] || vers->minor != version[1])
Packit aea12f
			diff = 1;
Packit aea12f
	}
Packit aea12f
Packit aea12f
	if (!IS_DTLS(session)) {
Packit aea12f
		if (htype == GNUTLS_HANDSHAKE_CLIENT_HELLO ||
Packit aea12f
		    htype == GNUTLS_HANDSHAKE_HELLO_RETRY_REQUEST ||
Packit aea12f
		    htype == GNUTLS_HANDSHAKE_SERVER_HELLO) {
Packit aea12f
			if (version[0] != 3) {
Packit aea12f
				gnutls_assert();
Packit aea12f
				_gnutls_record_log
Packit aea12f
				    ("REC[%p]: INVALID VERSION PACKET: (%d) %d.%d\n",
Packit aea12f
				     session, htype, version[0],
Packit aea12f
				     version[1]);
Packit aea12f
				return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
Packit aea12f
			}
Packit aea12f
		} else if (diff != 0) {
Packit aea12f
			/* Reject record packets that have a different version than the
Packit aea12f
			 * one negotiated. Note that this version is not protected by any
Packit aea12f
			 * mac. I don't really think that this check serves any purpose.
Packit aea12f
			 */
Packit aea12f
			gnutls_assert();
Packit aea12f
			_gnutls_record_log
Packit aea12f
			    ("REC[%p]: INVALID VERSION PACKET: (%d) %d.%d\n",
Packit aea12f
			     session, htype, version[0], version[1]);
Packit aea12f
Packit aea12f
			return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
Packit aea12f
		}
Packit aea12f
	} else {		/* DTLS */
Packit aea12f
Packit aea12f
		/* In DTLS the only information we have here is whether we
Packit aea12f
		 * expect a handshake message or not.
Packit aea12f
		 */
Packit aea12f
		if (htype == (gnutls_handshake_description_t) - 1) {
Packit aea12f
			if (diff) {
Packit aea12f
				/* Reject record packets that have a different version than the
Packit aea12f
				 * one negotiated. Note that this version is not protected by any
Packit aea12f
				 * mac. I don't really think that this check serves any purpose.
Packit aea12f
				 */
Packit aea12f
				gnutls_assert();
Packit aea12f
				_gnutls_record_log
Packit aea12f
				    ("REC[%p]: INVALID VERSION PACKET: (%d) %d.%d\n",
Packit aea12f
				     session, htype, version[0],
Packit aea12f
				     version[1]);
Packit aea12f
Packit aea12f
				return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
Packit aea12f
			}
Packit aea12f
		} else if (vers->id > GNUTLS_DTLS1_0 && version[0] > 254) {
Packit aea12f
			gnutls_assert();
Packit aea12f
			_gnutls_record_log
Packit aea12f
			    ("REC[%p]: INVALID DTLS VERSION PACKET: (%d) %d.%d\n",
Packit aea12f
			     session, htype, version[0], version[1]);
Packit aea12f
			return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
Packit aea12f
		} else if (vers->id == GNUTLS_DTLS0_9 && version[0] > 1) {
Packit aea12f
			gnutls_assert();
Packit aea12f
			_gnutls_record_log
Packit aea12f
			    ("REC[%p]: INVALID DTLS VERSION PACKET: (%d) %d.%d\n",
Packit aea12f
			     session, htype, version[0], version[1]);
Packit aea12f
			return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
Packit aea12f
		}
Packit aea12f
	}
Packit aea12f
Packit aea12f
	return 0;
Packit aea12f
}
Packit aea12f
Packit aea12f
static int
Packit aea12f
recv_hello_request(gnutls_session_t session, void *data,
Packit aea12f
		   uint32_t data_size)
Packit aea12f
{
Packit aea12f
	uint8_t type;
Packit aea12f
Packit aea12f
	if (session->security_parameters.entity == GNUTLS_SERVER)
Packit aea12f
		return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
Packit aea12f
Packit aea12f
	if (data_size < 1)
Packit aea12f
		return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
Packit aea12f
Packit aea12f
	if (session->internals.handshake_in_progress)
Packit aea12f
		return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
Packit aea12f
Packit aea12f
	type = ((uint8_t *) data)[0];
Packit aea12f
	if (type == GNUTLS_HANDSHAKE_HELLO_REQUEST) {
Packit aea12f
		if (IS_DTLS(session))
Packit aea12f
			session->internals.dtls.hsk_read_seq++;
Packit aea12f
		if (session->internals.flags & GNUTLS_AUTO_REAUTH) {
Packit aea12f
			session->internals.recv_state = RECV_STATE_REHANDSHAKE;
Packit aea12f
			return GNUTLS_E_AGAIN;
Packit aea12f
		} else {
Packit aea12f
			return GNUTLS_E_REHANDSHAKE;
Packit aea12f
		}
Packit aea12f
	} else {
Packit aea12f
		gnutls_assert();
Packit aea12f
		return GNUTLS_E_UNEXPECTED_PACKET;
Packit aea12f
	}
Packit aea12f
}
Packit aea12f
Packit aea12f
/* This function will check if the received record type is
Packit aea12f
 * the one we actually expect and adds it to the proper
Packit aea12f
 * buffer. The bufel will be deinitialized after calling
Packit aea12f
 * this function, even if it fails.
Packit aea12f
 */
Packit aea12f
static int
Packit aea12f
record_add_to_buffers(gnutls_session_t session,
Packit aea12f
		      struct tls_record_st *recv, content_type_t type,
Packit aea12f
		      gnutls_handshake_description_t htype,
Packit Service 991b93
		      uint64_t seq, mbuffer_st * bufel)
Packit aea12f
{
Packit aea12f
Packit aea12f
	int ret;
Packit aea12f
	const version_entry_st *ver = get_version(session);
Packit aea12f
Packit aea12f
	if ((recv->type == type)
Packit aea12f
	    && (type == GNUTLS_APPLICATION_DATA ||
Packit aea12f
		type == GNUTLS_CHANGE_CIPHER_SPEC ||
Packit aea12f
		type == GNUTLS_HANDSHAKE)) {
Packit aea12f
		if (bufel->msg.size == 0) {
Packit aea12f
			if (type == GNUTLS_APPLICATION_DATA) {
Packit aea12f
				/* this is needed to distinguish an empty
Packit aea12f
				 * message and EOF */
Packit aea12f
				ret = GNUTLS_E_AGAIN;
Packit aea12f
				goto cleanup;
Packit aea12f
			} else {
Packit aea12f
				ret =
Packit aea12f
				    gnutls_assert_val
Packit aea12f
				    (GNUTLS_E_UNEXPECTED_PACKET);
Packit aea12f
				goto unexpected_packet;
Packit aea12f
			}
Packit aea12f
		}
Packit aea12f
Packit aea12f
		/* application data cannot be inserted between (async) handshake
Packit aea12f
		 * messages */
Packit aea12f
		if (type == GNUTLS_APPLICATION_DATA &&
Packit aea12f
		    (session->internals.handshake_recv_buffer_size != 0 ||
Packit aea12f
		     session->internals.handshake_header_recv_buffer.length != 0)) {
Packit aea12f
			ret = gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
Packit aea12f
			goto unexpected_packet;
Packit aea12f
		}
Packit aea12f
Packit aea12f
		_gnutls_record_buffer_put(session, type, seq, bufel);
Packit aea12f
Packit aea12f
		/* if we received application data as expected then we
Packit aea12f
		 * deactivate the async timer */
Packit aea12f
		_dtls_async_timer_delete(session);
Packit aea12f
	} else {
Packit Service 991b93
		/* if the expected type is different than the received
Packit aea12f
		 */
Packit aea12f
		switch (recv->type) {
Packit aea12f
		case GNUTLS_ALERT:
Packit aea12f
			if (bufel->msg.size < 2) {
Packit aea12f
				ret =
Packit aea12f
				    gnutls_assert_val
Packit aea12f
				    (GNUTLS_E_UNEXPECTED_PACKET);
Packit aea12f
				goto unexpected_packet;
Packit aea12f
			}
Packit aea12f
Packit aea12f
			_gnutls_record_log
Packit aea12f
			    ("REC[%p]: Alert[%d|%d] - %s - was received\n",
Packit aea12f
			     session, bufel->msg.data[0],
Packit aea12f
			     bufel->msg.data[1],
Packit aea12f
			     gnutls_alert_get_name((int) bufel->msg.
Packit aea12f
						   data[1]));
Packit aea12f
Packit aea12f
			if (!session->internals.initial_negotiation_completed &&
Packit aea12f
			    session->internals.handshake_in_progress && STATE == STATE0) { /* handshake hasn't started */
Packit aea12f
				ret = gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
Packit aea12f
				goto unexpected_packet;
Packit aea12f
			}
Packit aea12f
Packit aea12f
			session->internals.last_alert = bufel->msg.data[1];
Packit aea12f
Packit aea12f
			/* if close notify is received and
Packit aea12f
			 * the alert is not fatal
Packit aea12f
			 */
Packit aea12f
			if (bufel->msg.data[1] == GNUTLS_A_CLOSE_NOTIFY
Packit aea12f
			    && bufel->msg.data[0] != GNUTLS_AL_FATAL) {
Packit Service 991b93
				/* If we have been expecting for an alert do
Packit aea12f
				 */
Packit aea12f
				session->internals.read_eof = 1;
Packit aea12f
				ret = GNUTLS_E_SESSION_EOF;
Packit aea12f
				goto cleanup;
Packit aea12f
			} else {
Packit aea12f
				/* if the alert is FATAL or WARNING
Packit aea12f
				 * return the appropriate message
Packit aea12f
				 */
Packit aea12f
				gnutls_assert();
Packit aea12f
				ret = GNUTLS_E_WARNING_ALERT_RECEIVED;
Packit aea12f
				if ((ver && ver->tls13_sem) || bufel->msg.data[0] == GNUTLS_AL_FATAL) {
Packit aea12f
					session_unresumable(session);
Packit aea12f
					session_invalidate(session);
Packit aea12f
					ret =
Packit aea12f
					    gnutls_assert_val
Packit aea12f
					    (GNUTLS_E_FATAL_ALERT_RECEIVED);
Packit aea12f
				}
Packit aea12f
				goto cleanup;
Packit aea12f
			}
Packit aea12f
			break;
Packit aea12f
Packit aea12f
		case GNUTLS_CHANGE_CIPHER_SPEC:
Packit aea12f
			if (!(IS_DTLS(session))) {
Packit aea12f
				ret = gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
Packit aea12f
				goto cleanup;
Packit aea12f
			}
Packit aea12f
Packit aea12f
			_gnutls_record_buffer_put(session, recv->type, seq,
Packit aea12f
						  bufel);
Packit aea12f
Packit aea12f
			break;
Packit aea12f
Packit aea12f
#ifdef ENABLE_HEARTBEAT
Packit aea12f
		case GNUTLS_HEARTBEAT:
Packit aea12f
			ret = _gnutls_heartbeat_handle(session, bufel);
Packit aea12f
			goto cleanup;
Packit aea12f
#endif
Packit aea12f
Packit aea12f
		case GNUTLS_APPLICATION_DATA:
Packit aea12f
			if (session->internals.
Packit aea12f
			    initial_negotiation_completed == 0) {
Packit aea12f
				ret =
Packit aea12f
				    gnutls_assert_val
Packit aea12f
				    (GNUTLS_E_UNEXPECTED_PACKET);
Packit aea12f
				goto unexpected_packet;
Packit aea12f
			}
Packit aea12f
Packit aea12f
			/* In TLS1.3 post-handshake authentication allow application
Packit aea12f
			 * data error code. */
Packit aea12f
			if ((ver && ver->tls13_sem) && type == GNUTLS_HANDSHAKE &&
Packit aea12f
			    htype == GNUTLS_HANDSHAKE_CERTIFICATE_PKT &&
Packit aea12f
			    session->internals.initial_negotiation_completed) {
Packit aea12f
				_gnutls_record_buffer_put(session, recv->type,
Packit aea12f
							  seq, bufel);
Packit aea12f
				return
Packit aea12f
				    gnutls_assert_val
Packit aea12f
				    (GNUTLS_E_GOT_APPLICATION_DATA);
Packit aea12f
			}
Packit aea12f
Packit aea12f
			/* The got_application data is only returned
Packit aea12f
			 * if expecting client hello (for rehandshake
Packit aea12f
			 * reasons). Otherwise it is an unexpected packet
Packit aea12f
			 */
Packit aea12f
			if (type == GNUTLS_ALERT
Packit aea12f
			    || ((htype == GNUTLS_HANDSHAKE_SERVER_HELLO ||
Packit aea12f
			         htype == GNUTLS_HANDSHAKE_CLIENT_HELLO ||
Packit aea12f
			         htype == GNUTLS_HANDSHAKE_HELLO_RETRY_REQUEST)
Packit aea12f
				&& type == GNUTLS_HANDSHAKE)) {
Packit aea12f
				/* even if data is unexpected put it into the buffer */
Packit aea12f
				_gnutls_record_buffer_put(session, recv->type,
Packit aea12f
							  seq, bufel);
Packit aea12f
				return
Packit aea12f
				    gnutls_assert_val
Packit aea12f
				    (GNUTLS_E_GOT_APPLICATION_DATA);
Packit aea12f
			} else {
Packit aea12f
				ret =
Packit aea12f
				    gnutls_assert_val
Packit aea12f
				    (GNUTLS_E_UNEXPECTED_PACKET);
Packit aea12f
				goto unexpected_packet;
Packit aea12f
			}
Packit aea12f
Packit aea12f
			break;
Packit aea12f
Packit aea12f
		case GNUTLS_HANDSHAKE:
Packit aea12f
			/* In DTLS we might receive a handshake replay from the peer to indicate
Packit aea12f
			 * the our last TLS handshake messages were not received.
Packit aea12f
			 */
Packit aea12f
			if (IS_DTLS(session)) {
Packit aea12f
				if (type == GNUTLS_CHANGE_CIPHER_SPEC) {
Packit aea12f
					ret =
Packit aea12f
					    gnutls_assert_val
Packit aea12f
					    (GNUTLS_E_UNEXPECTED_PACKET);
Packit aea12f
					goto unexpected_packet;
Packit aea12f
				}
Packit aea12f
Packit aea12f
				if (_dtls_is_async(session)
Packit aea12f
				    && _dtls_async_timer_active(session)) {
Packit aea12f
					if (session->security_parameters.
Packit aea12f
					    entity == GNUTLS_SERVER
Packit aea12f
					    && bufel->htype ==
Packit aea12f
					    GNUTLS_HANDSHAKE_CLIENT_HELLO)
Packit aea12f
					{
Packit aea12f
						/* client requested rehandshake. Delete the timer */
Packit aea12f
						_dtls_async_timer_delete
Packit aea12f
						    (session);
Packit aea12f
					} else {
Packit aea12f
						session->internals.
Packit aea12f
						    recv_state =
Packit aea12f
						    RECV_STATE_DTLS_RETRANSMIT;
Packit aea12f
						ret =
Packit aea12f
						    _dtls_retransmit
Packit aea12f
						    (session);
Packit aea12f
						if (ret == 0) {
Packit aea12f
							session->internals.
Packit aea12f
							    recv_state =
Packit aea12f
							    RECV_STATE_0;
Packit aea12f
							ret =
Packit aea12f
							    gnutls_assert_val
Packit aea12f
							    (GNUTLS_E_AGAIN);
Packit aea12f
							goto unexpected_packet;
Packit aea12f
						}
Packit aea12f
						goto cleanup;
Packit aea12f
					}
Packit aea12f
				}
Packit aea12f
			}
Packit aea12f
Packit aea12f
			/* retrieve async handshake messages */
Packit aea12f
			if (ver && ver->tls13_sem) {
Packit aea12f
				_gnutls_record_buffer_put(session, recv->type, seq, bufel);
Packit aea12f
Packit aea12f
				ret = _gnutls13_recv_async_handshake(session);
Packit aea12f
				if (ret < 0)
Packit aea12f
					return gnutls_assert_val(ret);
Packit aea12f
Packit aea12f
				/* bufel is now accounted */
Packit aea12f
				return GNUTLS_E_AGAIN;
Packit aea12f
			}
Packit aea12f
Packit aea12f
			/* This is legal if HELLO_REQUEST is received - and we are a client.
Packit aea12f
			 * If we are a server, a client may initiate a renegotiation at any time.
Packit aea12f
			 */
Packit aea12f
			if (session->security_parameters.entity ==
Packit aea12f
			    GNUTLS_SERVER
Packit aea12f
			    && session->internals.handshake_in_progress == 0
Packit aea12f
			    && bufel->htype ==
Packit aea12f
			    GNUTLS_HANDSHAKE_CLIENT_HELLO) {
Packit aea12f
				gnutls_assert();
Packit aea12f
				_gnutls_record_buffer_put(session,
Packit aea12f
							      recv->type,
Packit aea12f
							      seq, bufel);
Packit aea12f
				return GNUTLS_E_REHANDSHAKE;
Packit aea12f
			}
Packit aea12f
Packit aea12f
			/* If we are already in a handshake then a Hello
Packit aea12f
			 * Request is illegal. But here we don't really care
Packit aea12f
			 * since this message will never make it up here.
Packit aea12f
			 */
Packit aea12f
Packit aea12f
			/* So we accept it, if it is a Hello. If not, this will
Packit aea12f
			 * fail and trigger flight retransmissions after some time. */
Packit aea12f
			ret =
Packit aea12f
			    recv_hello_request(session,
Packit aea12f
					       bufel->msg.data,
Packit aea12f
					       bufel->msg.size);
Packit aea12f
			goto unexpected_packet;
Packit aea12f
		default:
Packit aea12f
Packit aea12f
			_gnutls_record_log
Packit aea12f
			    ("REC[%p]: Received unexpected packet %d (%s) expecting %d (%s)\n",
Packit aea12f
			     session, recv->type,
Packit aea12f
			     _gnutls_packet2str(recv->type), type,
Packit aea12f
			     _gnutls_packet2str(type));
Packit aea12f
Packit aea12f
			gnutls_assert();
Packit aea12f
			ret = GNUTLS_E_UNEXPECTED_PACKET;
Packit aea12f
			goto unexpected_packet;
Packit aea12f
		}
Packit aea12f
	}
Packit aea12f
Packit aea12f
	return 0;
Packit aea12f
Packit aea12f
 unexpected_packet:
Packit aea12f
Packit aea12f
	if (IS_DTLS(session) && ret != GNUTLS_E_REHANDSHAKE) {
Packit aea12f
		_mbuffer_xfree(&bufel);
Packit aea12f
		RETURN_DTLS_EAGAIN_OR_TIMEOUT(session, ret);
Packit aea12f
	}
Packit aea12f
Packit aea12f
 cleanup:
Packit aea12f
	_mbuffer_xfree(&bufel);
Packit aea12f
	return ret;
Packit aea12f
Packit aea12f
}
Packit aea12f
Packit aea12f
Packit aea12f
/* Checks the record headers and returns the length, version and
Packit aea12f
 * content type.
Packit aea12f
 */
Packit aea12f
static void
Packit aea12f
record_read_headers(gnutls_session_t session,
Packit aea12f
		    uint8_t headers[MAX_RECORD_HEADER_SIZE],
Packit aea12f
		    content_type_t type,
Packit aea12f
		    gnutls_handshake_description_t htype,
Packit aea12f
		    struct tls_record_st *record)
Packit aea12f
{
Packit aea12f
Packit Service 991b93
	/* Read the first two bytes to determine if this is a
Packit Service 991b93
	 * version 2 message
Packit aea12f
	 */
Packit aea12f
Packit aea12f
#ifdef ENABLE_SSL2
Packit aea12f
	if (htype == GNUTLS_HANDSHAKE_CLIENT_HELLO
Packit aea12f
	    && type == GNUTLS_HANDSHAKE && headers[0] > 127
Packit aea12f
	    && !(IS_DTLS(session))) {
Packit aea12f
Packit aea12f
		/* if msb set and expecting handshake message
Packit Service 991b93
		 * it should be SSL 2 hello
Packit aea12f
		 */
Packit aea12f
		record->version[0] = 3;	/* assume SSL 3.0 */
Packit aea12f
		record->version[1] = 0;
Packit aea12f
Packit aea12f
		record->length = (((headers[0] & 0x7f) << 8)) | headers[1];
Packit aea12f
Packit aea12f
		/* SSL 2.0 headers */
Packit aea12f
		record->header_size = record->packet_size = 2;
Packit aea12f
		record->type = GNUTLS_HANDSHAKE;	/* we accept only v2 client hello
Packit aea12f
							 */
Packit aea12f
Packit aea12f
		/* in order to assist the handshake protocol.
Packit aea12f
		 * V2 compatibility is a mess.
Packit aea12f
		 */
Packit aea12f
		record->v2 = 1;
Packit aea12f
		record->epoch = 0;
Packit aea12f
		memset(&record->sequence, 0, sizeof(record->sequence));
Packit aea12f
Packit aea12f
		_gnutls_record_log
Packit aea12f
		    ("REC[%p]: SSL 2.0 %s packet received. Length: %d\n",
Packit aea12f
		     session, _gnutls_packet2str(record->type),
Packit aea12f
		     record->length);
Packit aea12f
Packit aea12f
	} else
Packit aea12f
#endif
Packit aea12f
	{
Packit aea12f
		/* dtls version 1.0 and TLS version 1.x */
Packit aea12f
#ifdef ENABLE_SSL2
Packit aea12f
		record->v2 = 0;
Packit aea12f
#endif
Packit aea12f
Packit aea12f
		record->type = headers[0];
Packit aea12f
		record->version[0] = headers[1];
Packit aea12f
		record->version[1] = headers[2];
Packit aea12f
Packit aea12f
		if (IS_DTLS(session)) {
Packit Service 991b93
			record->sequence = _gnutls_read_uint64(&headers[3]);
Packit aea12f
			record->length = _gnutls_read_uint16(&headers[11]);
Packit Service 991b93
			record->epoch = record->sequence >> 48;
Packit aea12f
		} else {
Packit aea12f
			memset(&record->sequence, 0,
Packit aea12f
			       sizeof(record->sequence));
Packit aea12f
			record->length = _gnutls_read_uint16(&headers[3]);
Packit aea12f
			record->epoch = session->security_parameters.epoch_read;
Packit aea12f
		}
Packit aea12f
Packit aea12f
		_gnutls_record_log
Packit aea12f
		    ("REC[%p]: SSL %d.%d %s packet received. Epoch %d, length: %d\n",
Packit aea12f
		     session, (int) record->version[0],
Packit aea12f
		     (int) record->version[1],
Packit aea12f
		     _gnutls_packet2str(record->type), (int) record->epoch,
Packit aea12f
		     record->length);
Packit aea12f
Packit aea12f
	}
Packit aea12f
Packit aea12f
	record->packet_size += record->length;
Packit aea12f
}
Packit aea12f
Packit aea12f
Packit Service 991b93
static int recv_headers(gnutls_session_t session,
Packit aea12f
			record_parameters_st *record_params,
Packit aea12f
			content_type_t type,
Packit aea12f
			gnutls_handshake_description_t htype,
Packit aea12f
			struct tls_record_st *record, unsigned int *ms)
Packit aea12f
{
Packit aea12f
	int ret;
Packit aea12f
	gnutls_datum_t raw;	/* raw headers */
Packit aea12f
	/* Read the headers.
Packit aea12f
	 */
Packit aea12f
	record->header_size = record->packet_size =
Packit aea12f
	    RECORD_HEADER_SIZE(session);
Packit aea12f
Packit aea12f
	ret =
Packit aea12f
	    _gnutls_io_read_buffered(session, record->header_size, -1, ms);
Packit aea12f
	if (ret != record->header_size) {
Packit aea12f
		if (ret < 0 && gnutls_error_is_fatal(ret) == 0)
Packit aea12f
			return ret;
Packit aea12f
Packit aea12f
		if (ret > 0)
Packit aea12f
			ret = GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
Packit aea12f
		else if (ret == 0)
Packit aea12f
			ret = GNUTLS_E_PREMATURE_TERMINATION;
Packit aea12f
Packit aea12f
		return gnutls_assert_val(ret);
Packit aea12f
	}
Packit aea12f
Packit Service 991b93
	ret = _mbuffer_linearize_align16(&session->internals.record_recv_buffer,
Packit aea12f
		get_total_headers2(session, record_params));
Packit aea12f
	if (ret < 0)
Packit aea12f
		return gnutls_assert_val(ret);
Packit aea12f
Packit aea12f
	_mbuffer_head_get_first(&session->internals.record_recv_buffer,
Packit aea12f
				&raw;;
Packit aea12f
	if (raw.size < RECORD_HEADER_SIZE(session))
Packit aea12f
		return
Packit aea12f
		    gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
Packit aea12f
Packit aea12f
	record_read_headers(session, raw.data, type, htype, record);
Packit aea12f
Packit aea12f
	/* Check if the DTLS epoch is valid */
Packit aea12f
	if (IS_DTLS(session)) {
Packit aea12f
		if (_gnutls_epoch_is_valid(session, record->epoch) == 0) {
Packit aea12f
			_gnutls_audit_log(session,
Packit Service 991b93
					  "Discarded message[%lu] with invalid epoch %u.\n",
Packit Service 991b93
					  (unsigned long)record->sequence,
Packit Service 991b93
					  (unsigned int) (record->sequence >> 48));
Packit aea12f
			gnutls_assert();
Packit aea12f
			/* doesn't matter, just a fatal error */
Packit aea12f
			return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
Packit aea12f
		}
Packit aea12f
	}
Packit aea12f
Packit aea12f
	/* Here we check if the Type of the received packet is
Packit Service 991b93
	 * ok.
Packit aea12f
	 */
Packit aea12f
	if ((ret = check_recv_type(session, record->type)) < 0)
Packit aea12f
		return gnutls_assert_val(ret);
Packit aea12f
Packit aea12f
	/* Here we check if the advertized version is the one we
Packit aea12f
	 * negotiated in the handshake.
Packit aea12f
	 */
Packit aea12f
	if ((ret =
Packit aea12f
	     record_check_version(session, htype, record->version)) < 0)
Packit aea12f
		return gnutls_assert_val(ret);
Packit aea12f
Packit aea12f
	if (record->length == 0 || record->length > max_record_recv_size(session)) {
Packit aea12f
		_gnutls_audit_log
Packit Service 991b93
		    (session, "Received packet with illegal length: %u (max: %u)\n",
Packit Service 991b93
		     (unsigned int) record->length, (unsigned)max_record_recv_size(session));
Packit aea12f
Packit aea12f
		if (record->length == 0) {
Packit aea12f
			/* Empty, unencrypted records are always unexpected. */
Packit aea12f
			if (record_params->cipher->id == GNUTLS_CIPHER_NULL)
Packit aea12f
				return
Packit aea12f
				    gnutls_assert_val
Packit aea12f
				    (GNUTLS_E_UNEXPECTED_PACKET);
Packit aea12f
Packit aea12f
			return gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
Packit aea12f
		}
Packit aea12f
		return
Packit aea12f
		    gnutls_assert_val(GNUTLS_E_RECORD_OVERFLOW);
Packit aea12f
	}
Packit aea12f
Packit aea12f
	_gnutls_record_log
Packit aea12f
	    ("REC[%p]: Expected Packet %s(%d)\n", session,
Packit aea12f
	     _gnutls_packet2str(type), type);
Packit aea12f
	_gnutls_record_log
Packit aea12f
	    ("REC[%p]: Received Packet %s(%d) with length: %d\n", session,
Packit aea12f
	     _gnutls_packet2str(record->type), record->type,
Packit aea12f
	     record->length);
Packit aea12f
Packit aea12f
Packit aea12f
	return 0;
Packit aea12f
}
Packit aea12f
Packit aea12f
/* @ms: is the number of milliseconds to wait for data. Use zero for indefinite.
Packit aea12f
 *
Packit Service 991b93
 * This will receive record layer packets and add them to
Packit aea12f
 * application_data_buffer and handshake_data_buffer.
Packit aea12f
 *
Packit aea12f
 * If the htype is not -1 then handshake timeouts
Packit aea12f
 * will be enforced.
Packit aea12f
 */
Packit aea12f
ssize_t
Packit aea12f
_gnutls_recv_in_buffers(gnutls_session_t session, content_type_t type,
Packit aea12f
			gnutls_handshake_description_t htype,
Packit aea12f
			unsigned int ms)
Packit aea12f
{
Packit Service 991b93
	uint64_t packet_sequence;
Packit aea12f
	gnutls_datum_t ciphertext;
Packit aea12f
	mbuffer_st *bufel = NULL, *decrypted = NULL;
Packit aea12f
	gnutls_datum_t t;
Packit aea12f
	int ret;
Packit aea12f
	unsigned int n_retries = 0;
Packit aea12f
	record_parameters_st *record_params;
Packit aea12f
	record_state_st *record_state;
Packit aea12f
	struct tls_record_st record;
Packit aea12f
	const version_entry_st *vers = get_version(session);
Packit aea12f
Packit aea12f
 begin:
Packit aea12f
Packit aea12f
	if (n_retries > DEFAULT_MAX_EMPTY_RECORDS) {
Packit aea12f
		gnutls_assert();
Packit aea12f
		return GNUTLS_E_TOO_MANY_EMPTY_PACKETS;
Packit aea12f
	}
Packit aea12f
Packit aea12f
	if (session->internals.read_eof != 0) {
Packit aea12f
		/* if we have already read an EOF
Packit aea12f
		 */
Packit aea12f
		return 0;
Packit aea12f
	} else if (session_is_valid(session) != 0
Packit aea12f
		   || session->internals.may_not_read != 0)
Packit aea12f
		return gnutls_assert_val(GNUTLS_E_INVALID_SESSION);
Packit aea12f
Packit aea12f
	/* get the record state parameters */
Packit aea12f
	ret =
Packit aea12f
	    _gnutls_epoch_get(session, EPOCH_READ_CURRENT, &record_params);
Packit aea12f
	if (ret < 0)
Packit aea12f
		return gnutls_assert_val(ret);
Packit aea12f
Packit aea12f
	/* Safeguard against processing data with an incomplete cipher state. */
Packit aea12f
	if (!record_params->initialized)
Packit aea12f
		return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit aea12f
Packit aea12f
	record_state = &record_params->read;
Packit aea12f
Packit aea12f
	/* receive headers */
Packit aea12f
	ret = recv_headers(session, record_params, type, htype, &record, (!(session->internals.flags & GNUTLS_NONBLOCK))?&ms:0);
Packit aea12f
	if (ret < 0) {
Packit aea12f
		ret = gnutls_assert_val_fatal(ret);
Packit aea12f
		goto recv_error;
Packit aea12f
	}
Packit aea12f
Packit aea12f
	if (IS_DTLS(session))
Packit Service 991b93
		packet_sequence = record.sequence;
Packit aea12f
	else
Packit Service 991b93
		packet_sequence = record_state->sequence_number;
Packit aea12f
Packit aea12f
	/* Read the packet data and insert it to record_recv_buffer.
Packit aea12f
	 */
Packit aea12f
	ret =
Packit aea12f
	    _gnutls_io_read_buffered(session, record.packet_size,
Packit aea12f
				     record.type, (!(session->internals.flags & GNUTLS_NONBLOCK))?&ms:0);
Packit aea12f
	if (ret != record.packet_size) {
Packit aea12f
		gnutls_assert();
Packit aea12f
		goto recv_error;
Packit aea12f
	}
Packit aea12f
Packit aea12f
	/* ok now we are sure that we have read all the data - so
Packit aea12f
	 * move on !
Packit aea12f
	 */
Packit Service 991b93
	ret = _mbuffer_linearize_align16(&session->internals.record_recv_buffer,
Packit aea12f
		get_total_headers2(session, record_params));
Packit aea12f
	if (ret < 0)
Packit aea12f
		return gnutls_assert_val(ret);
Packit aea12f
Packit aea12f
	bufel =
Packit aea12f
	    _mbuffer_head_get_first(&session->internals.record_recv_buffer,
Packit aea12f
				    NULL);
Packit aea12f
	if (bufel == NULL)
Packit aea12f
		return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit aea12f
Packit aea12f
	if (vers && vers->tls13_sem && record.type == GNUTLS_CHANGE_CIPHER_SPEC) {
Packit aea12f
		/* if the CCS has value other than 0x01, or arrives
Packit aea12f
		 * after Finished, abort the connection */
Packit aea12f
		if (record.length != 1 ||
Packit aea12f
		    *((uint8_t *) _mbuffer_get_udata_ptr(bufel) +
Packit aea12f
		      record.header_size) != 0x01 ||
Packit aea12f
		    !session->internals.handshake_in_progress)
Packit aea12f
			return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
Packit aea12f
Packit aea12f
		_gnutls_read_log("discarding change cipher spec in TLS1.3\n");
Packit aea12f
		/* we use the same mechanism to retry as when
Packit aea12f
		 * receiving multiple empty TLS packets */
Packit aea12f
		bufel =
Packit aea12f
		    _mbuffer_head_pop_first(&session->internals.
Packit aea12f
					    record_recv_buffer);
Packit aea12f
		_mbuffer_xfree(&bufel);
Packit aea12f
		n_retries++;
Packit aea12f
		goto begin;
Packit aea12f
	}
Packit aea12f
Packit aea12f
	/* We allocate the maximum possible to allow few compressed bytes to expand to a
Packit aea12f
	 * full record. Moreover we add space for any pad and the MAC (in case
Packit aea12f
	 * they are encrypted).
Packit aea12f
	 */
Packit aea12f
	ret = max_decrypted_size(session) + MAX_PAD_SIZE + MAX_HASH_SIZE;
Packit aea12f
	decrypted = _mbuffer_alloc_align16(ret, 0);
Packit aea12f
	if (decrypted == NULL)
Packit aea12f
		return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
Packit aea12f
Packit aea12f
	_mbuffer_set_udata_size(decrypted, ret);
Packit aea12f
	ciphertext.data =
Packit aea12f
	    (uint8_t *) _mbuffer_get_udata_ptr(bufel) + record.header_size;
Packit aea12f
	ciphertext.size = record.length;
Packit aea12f
Packit Service 991b93
	/* decrypt the data we got.
Packit aea12f
	 */
Packit aea12f
	t.data = _mbuffer_get_udata_ptr(decrypted);
Packit aea12f
	t.size = _mbuffer_get_udata_size(decrypted);
Packit aea12f
	ret =
Packit aea12f
	    _gnutls_decrypt(session, &ciphertext, &t,
Packit aea12f
			    &record.type, record_params, packet_sequence);
Packit aea12f
	if (ret >= 0)
Packit aea12f
		_mbuffer_set_udata_size(decrypted, ret);
Packit aea12f
Packit aea12f
	_mbuffer_head_remove_bytes(&session->internals.record_recv_buffer,
Packit aea12f
				   record.header_size + record.length);
Packit aea12f
Packit aea12f
	if (session->security_parameters.entity == GNUTLS_SERVER &&
Packit aea12f
	    session->internals.hsk_flags & HSK_EARLY_DATA_IN_FLIGHT) {
Packit aea12f
		if (session->internals.hsk_flags & HSK_EARLY_DATA_ACCEPTED) {
Packit aea12f
			if (ret < 0 ||
Packit aea12f
			    /* early data must always be encrypted, treat it
Packit aea12f
			     * as decryption failure if otherwise */
Packit aea12f
			    record_params->cipher->id == GNUTLS_CIPHER_NULL) {
Packit aea12f
				_gnutls_record_log
Packit aea12f
					("REC[%p]: failed to decrypt early data, in epoch %d\n",
Packit aea12f
					 session,
Packit aea12f
						record_params->epoch);
Packit aea12f
				ret = GNUTLS_E_DECRYPTION_FAILED;
Packit aea12f
				goto sanity_check_error;
Packit aea12f
			} else if (record.type == GNUTLS_APPLICATION_DATA) {
Packit aea12f
				size_t decrypted_length =
Packit aea12f
					_mbuffer_get_udata_size(decrypted);
Packit aea12f
				_gnutls_record_log
Packit aea12f
					("REC[%p]: decrypted early data with length: %d, in epoch %d\n",
Packit aea12f
					 session,
Packit aea12f
					 (int) decrypted_length,
Packit aea12f
					 record_params->epoch);
Packit aea12f
				if (decrypted_length >
Packit aea12f
				    session->security_parameters.max_early_data_size -
Packit aea12f
				    session->internals.early_data_received) {
Packit aea12f
					_gnutls_record_log
Packit aea12f
						("REC[%p]: max_early_data_size exceeded\n",
Packit aea12f
						 session);
Packit aea12f
					ret = GNUTLS_E_UNEXPECTED_PACKET;
Packit aea12f
					goto sanity_check_error;
Packit aea12f
				}
Packit aea12f
Packit aea12f
				_mbuffer_enqueue(&session->internals.early_data_recv_buffer, decrypted);
Packit aea12f
				session->internals.early_data_received +=
Packit aea12f
					decrypted_length;
Packit aea12f
Packit aea12f
				/* Increase sequence number. We do both for TLS and DTLS, since in
Packit aea12f
				 * DTLS we also rely on that number (roughly) since it may get reported
Packit aea12f
				 * to application via gnutls_record_get_state().
Packit aea12f
				 */
Packit aea12f
				if (sequence_increment(session, &record_state->sequence_number) != 0) {
Packit aea12f
					session_invalidate(session);
Packit aea12f
					gnutls_assert();
Packit aea12f
					ret = GNUTLS_E_RECORD_LIMIT_REACHED;
Packit aea12f
					goto sanity_check_error;
Packit aea12f
				}
Packit aea12f
Packit aea12f
				/* decrypted is now accounted */
Packit aea12f
				return GNUTLS_E_AGAIN;
Packit aea12f
			}
Packit aea12f
		} else {
Packit aea12f
			/* We do not accept early data: skip decryption
Packit aea12f
			 * failure up to max_early_data_size. Otherwise,
Packit aea12f
			 * if the record is properly decrypted, treat it as
Packit aea12f
			 * the start of client's second flight.
Packit aea12f
			 */
Packit aea12f
			if (record.type == GNUTLS_APPLICATION_DATA &&
Packit aea12f
			    (ret < 0 ||
Packit aea12f
			     /* early data must always be encrypted, treat it
Packit aea12f
			      * as decryption failure if otherwise */
Packit aea12f
			     record_params->cipher->id == GNUTLS_CIPHER_NULL)) {
Packit aea12f
				if (record.length >
Packit aea12f
				    session->security_parameters.max_early_data_size -
Packit aea12f
				    session->internals.early_data_received) {
Packit aea12f
					_gnutls_record_log
Packit aea12f
						("REC[%p]: max_early_data_size exceeded\n",
Packit aea12f
						 session);
Packit aea12f
					ret = GNUTLS_E_UNEXPECTED_PACKET;
Packit aea12f
					goto sanity_check_error;
Packit aea12f
				}
Packit aea12f
Packit Service 991b93
				_gnutls_record_log("REC[%p]: Discarded early data[%lu] due to invalid decryption, length: %u\n",
Packit aea12f
						   session,
Packit Service 991b93
						   (unsigned long)packet_sequence,
Packit aea12f
						   (unsigned int)
Packit aea12f
						   record.length);
Packit aea12f
				session->internals.early_data_received += record.length;
Packit aea12f
				/* silently discard received data */
Packit aea12f
				_mbuffer_xfree(&decrypted);
Packit aea12f
				return gnutls_assert_val(GNUTLS_E_AGAIN);
Packit aea12f
			} else {
Packit aea12f
				session->internals.hsk_flags &= ~HSK_EARLY_DATA_IN_FLIGHT;
Packit aea12f
			}
Packit aea12f
		}
Packit aea12f
	}
Packit aea12f
Packit aea12f
	if (ret < 0) {
Packit aea12f
		gnutls_assert();
Packit aea12f
		_gnutls_audit_log(session,
Packit Service 991b93
				  "Discarded message[%lu] due to invalid decryption\n",
Packit Service 991b93
				  (unsigned long)packet_sequence);
Packit aea12f
		goto sanity_check_error;
Packit aea12f
	}
Packit aea12f
Packit aea12f
	if (IS_DTLS(session)) {
Packit aea12f
		/* check for duplicates. We check after the message
Packit aea12f
		 * is processed and authenticated to avoid someone
Packit aea12f
		 * messing with our windows. */
Packit aea12f
		if (likely(!(session->internals.flags & GNUTLS_NO_REPLAY_PROTECTION))) {
Packit aea12f
			ret = _dtls_record_check(record_params, packet_sequence);
Packit aea12f
			if (ret < 0) {
Packit aea12f
				_gnutls_record_log
Packit Service 991b93
				    ("REC[%p]: Discarded duplicate message[%u.%lu]: %s\n",
Packit aea12f
				     session,
Packit Service 991b93
				     (unsigned int) (record.sequence >> 48),
Packit Service 991b93
				     (unsigned long) (packet_sequence),
Packit aea12f
				     _gnutls_packet2str(record.type));
Packit aea12f
				goto sanity_check_error;
Packit aea12f
			}
Packit aea12f
		}
Packit aea12f
Packit aea12f
		_gnutls_record_log
Packit Service 991b93
		    ("REC[%p]: Decrypted Packet[%u.%lu] %s(%d) with length: %d\n",
Packit aea12f
		     session,
Packit Service 991b93
		     (unsigned int) (record.sequence >> 48),
Packit Service 991b93
		     (unsigned long) packet_sequence,
Packit aea12f
		     _gnutls_packet2str(record.type), record.type,
Packit aea12f
		     (int) _mbuffer_get_udata_size(decrypted));
Packit aea12f
Packit aea12f
		/* store the last valid sequence number. We don't use that internally but
Packit aea12f
		 * callers of gnutls_record_get_state() could take advantage of it. */
Packit Service 991b93
		record_state->sequence_number = record.sequence;
Packit aea12f
	} else {
Packit aea12f
		_gnutls_record_log
Packit Service 991b93
		    ("REC[%p]: Decrypted Packet[%lu] %s(%d) with length: %d\n",
Packit aea12f
		     session,
Packit Service 991b93
		     (unsigned long) packet_sequence,
Packit aea12f
		     _gnutls_packet2str(record.type), record.type,
Packit aea12f
		     (int) _mbuffer_get_udata_size(decrypted));
Packit aea12f
Packit aea12f
	}
Packit aea12f
Packit aea12f
	/* Increase sequence number. We do both for TLS and DTLS, since in
Packit aea12f
	 * DTLS we also rely on that number (roughly) since it may get reported
Packit aea12f
	 * to application via gnutls_record_get_state().
Packit aea12f
	 */
Packit aea12f
	if (sequence_increment(session, &record_state->sequence_number) != 0) {
Packit aea12f
		session_invalidate(session);
Packit aea12f
		gnutls_assert();
Packit aea12f
		ret = GNUTLS_E_RECORD_LIMIT_REACHED;
Packit aea12f
		goto sanity_check_error;
Packit aea12f
	}
Packit aea12f
Packit Service 991b93
/* (originally for) TLS 1.0 CBC protection.
Packit aea12f
 * Actually this code is called if we just received
Packit aea12f
 * an empty packet. An empty TLS packet is usually
Packit aea12f
 * sent to protect some vulnerabilities in the CBC mode.
Packit aea12f
 * In that case we go to the beginning and start reading
Packit aea12f
 * the next packet.
Packit aea12f
 */
Packit aea12f
	if (_mbuffer_get_udata_size(decrypted) == 0 &&
Packit aea12f
	    /* Under TLS 1.3, there are only AEAD ciphers and this
Packit aea12f
	     * logic is meaningless. Moreover, the implementation need
Packit aea12f
	     * to send correct alert upon receiving empty messages in
Packit aea12f
	     * certain occasions. Skip this and leave
Packit aea12f
	     * record_add_to_buffers() to handle the empty
Packit aea12f
	     * messages. */
Packit aea12f
	    !(vers && vers->tls13_sem)) {
Packit aea12f
		_mbuffer_xfree(&decrypted);
Packit aea12f
		n_retries++;
Packit aea12f
		goto begin;
Packit aea12f
	}
Packit aea12f
Packit aea12f
	if (_mbuffer_get_udata_size(decrypted) > max_decrypted_size(session)) {
Packit aea12f
		_gnutls_audit_log
Packit aea12f
		    (session, "Received packet with illegal length: %u\n",
Packit aea12f
		     (unsigned int) ret);
Packit aea12f
Packit aea12f
		ret = gnutls_assert_val(GNUTLS_E_RECORD_OVERFLOW);
Packit aea12f
		goto sanity_check_error;
Packit aea12f
	}
Packit aea12f
Packit aea12f
#ifdef ENABLE_SSL2
Packit aea12f
	if (record.v2) {
Packit aea12f
		decrypted->htype = GNUTLS_HANDSHAKE_CLIENT_HELLO_V2;
Packit aea12f
	} else
Packit aea12f
#endif
Packit aea12f
	{
Packit aea12f
		uint8_t *p = _mbuffer_get_udata_ptr(decrypted);
Packit aea12f
		decrypted->htype = p[0];
Packit aea12f
	}
Packit aea12f
Packit aea12f
	ret =
Packit aea12f
	    record_add_to_buffers(session, &record, type, htype,
Packit aea12f
				  packet_sequence, decrypted);
Packit aea12f
Packit aea12f
	/* decrypted is now either deinitialized or buffered somewhere else */
Packit aea12f
Packit aea12f
	if (ret < 0)
Packit aea12f
		return gnutls_assert_val(ret);
Packit aea12f
Packit aea12f
	return ret;
Packit aea12f
Packit aea12f
 discard:
Packit aea12f
	session->internals.dtls.packets_dropped++;
Packit aea12f
Packit aea12f
	/* discard the whole received fragment. */
Packit aea12f
	bufel =
Packit aea12f
	    _mbuffer_head_pop_first(&session->internals.
Packit aea12f
				    record_recv_buffer);
Packit aea12f
	_mbuffer_xfree(&bufel);
Packit aea12f
	return gnutls_assert_val(GNUTLS_E_AGAIN);
Packit aea12f
Packit aea12f
 sanity_check_error:
Packit aea12f
	if (IS_DTLS(session)) {
Packit aea12f
		session->internals.dtls.packets_dropped++;
Packit aea12f
		ret = gnutls_assert_val(GNUTLS_E_AGAIN);
Packit aea12f
		goto cleanup;
Packit aea12f
	}
Packit aea12f
Packit aea12f
	session_unresumable(session);
Packit aea12f
	session_invalidate(session);
Packit aea12f
Packit aea12f
 cleanup:
Packit aea12f
	_mbuffer_xfree(&decrypted);
Packit aea12f
	return ret;
Packit aea12f
Packit aea12f
 recv_error:
Packit aea12f
	if (ret < 0
Packit aea12f
	    && (gnutls_error_is_fatal(ret) == 0
Packit aea12f
		|| ret == GNUTLS_E_TIMEDOUT))
Packit aea12f
		return ret;
Packit aea12f
Packit aea12f
	if (type == GNUTLS_ALERT) {	/* we were expecting close notify */
Packit aea12f
		session_invalidate(session);
Packit aea12f
		gnutls_assert();
Packit aea12f
		return 0;
Packit aea12f
	}
Packit aea12f
Packit aea12f
	if (IS_DTLS(session) && (ret == GNUTLS_E_DECRYPTION_FAILED ||
Packit aea12f
		ret == GNUTLS_E_UNSUPPORTED_VERSION_PACKET ||
Packit aea12f
		ret == GNUTLS_E_UNEXPECTED_PACKET_LENGTH ||
Packit aea12f
		ret == GNUTLS_E_RECORD_OVERFLOW ||
Packit aea12f
		ret == GNUTLS_E_UNEXPECTED_PACKET ||
Packit aea12f
		ret == GNUTLS_E_ERROR_IN_FINISHED_PACKET ||
Packit aea12f
		ret == GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET)) {
Packit aea12f
		goto discard;
Packit aea12f
	}
Packit aea12f
Packit aea12f
	session_invalidate(session);
Packit aea12f
	session_unresumable(session);
Packit aea12f
Packit aea12f
	if (ret == 0)
Packit aea12f
		return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
Packit aea12f
	else
Packit aea12f
		return ret;
Packit aea12f
}
Packit aea12f
Packit aea12f
/* Returns a value greater than zero (>= 0) if buffers should be checked
Packit aea12f
 * for data. */
Packit aea12f
static ssize_t
Packit aea12f
check_session_status(gnutls_session_t session, unsigned ms)
Packit aea12f
{
Packit aea12f
	int ret;
Packit aea12f
Packit aea12f
	if (session->internals.read_eof != 0) {
Packit aea12f
		/* if we have already read an EOF
Packit aea12f
		 */
Packit aea12f
		return 0;
Packit aea12f
	} else if (session_is_valid(session) != 0
Packit aea12f
		   || session->internals.may_not_read != 0) {
Packit aea12f
		gnutls_assert();
Packit aea12f
		return GNUTLS_E_INVALID_SESSION;
Packit aea12f
	}
Packit aea12f
Packit aea12f
	switch (session->internals.recv_state) {
Packit aea12f
	case RECV_STATE_REAUTH:
Packit aea12f
		session->internals.recv_state = RECV_STATE_0;
Packit aea12f
Packit aea12f
		ret = gnutls_reauth(session, 0);
Packit aea12f
		if (ret < 0) {
Packit aea12f
			/* a temp or fatal error, make sure we reset the state
Packit aea12f
			 * so we can resume on temp errors */
Packit aea12f
			session->internals.recv_state = RECV_STATE_REAUTH;
Packit aea12f
			return gnutls_assert_val(ret);
Packit aea12f
		}
Packit aea12f
Packit aea12f
		return 1;
Packit aea12f
	case RECV_STATE_REHANDSHAKE:
Packit aea12f
		session->internals.recv_state = RECV_STATE_0;
Packit aea12f
Packit aea12f
		ret = gnutls_handshake(session);
Packit aea12f
		if (ret < 0) {
Packit aea12f
			/* a temp or fatal error, make sure we reset the state
Packit aea12f
			 * so we can resume on temp errors */
Packit aea12f
			session->internals.recv_state = RECV_STATE_REHANDSHAKE;
Packit aea12f
			return gnutls_assert_val(ret);
Packit aea12f
		}
Packit aea12f
Packit aea12f
		return 1;
Packit aea12f
	case RECV_STATE_ASYNC_HANDSHAKE:
Packit aea12f
		ret = _gnutls_recv_in_buffers(session, GNUTLS_HANDSHAKE, -1, ms);
Packit aea12f
		if (ret < 0 && ret != GNUTLS_E_SESSION_EOF)
Packit aea12f
			return gnutls_assert_val(ret);
Packit aea12f
Packit aea12f
		ret = _gnutls13_recv_async_handshake(session);
Packit aea12f
		if (ret < 0)
Packit aea12f
			return gnutls_assert_val(ret);
Packit aea12f
Packit aea12f
		return GNUTLS_E_AGAIN;
Packit aea12f
	case RECV_STATE_EARLY_START_HANDLING:
Packit aea12f
	case RECV_STATE_FALSE_START_HANDLING:
Packit aea12f
		return 1;
Packit aea12f
	case RECV_STATE_FALSE_START:
Packit aea12f
		/* if false start is not complete we always expect for handshake packets
Packit aea12f
		 * prior to anything else. */
Packit aea12f
		if (session->security_parameters.entity != GNUTLS_CLIENT ||
Packit aea12f
		    !(session->internals.flags & GNUTLS_ENABLE_FALSE_START))
Packit aea12f
			return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit aea12f
Packit aea12f
		/* Attempt to complete handshake - we only need to receive */
Packit aea12f
		session->internals.recv_state = RECV_STATE_FALSE_START_HANDLING;
Packit aea12f
		ret = gnutls_handshake(session);
Packit aea12f
		if (ret < 0) {
Packit aea12f
			/* a temp or fatal error, make sure we reset the state
Packit aea12f
			 * so we can resume on temp errors */
Packit aea12f
			session->internals.recv_state = RECV_STATE_FALSE_START;
Packit aea12f
			return gnutls_assert_val(ret);
Packit aea12f
		}
Packit aea12f
Packit aea12f
		session->internals.recv_state = RECV_STATE_0;
Packit aea12f
		return 1;
Packit aea12f
	case RECV_STATE_EARLY_START:
Packit aea12f
		/* if early start is not complete we always expect for handshake packets
Packit aea12f
		 * prior to anything else. */
Packit aea12f
		if (session->security_parameters.entity != GNUTLS_SERVER ||
Packit aea12f
		    !(session->internals.flags & GNUTLS_ENABLE_EARLY_START))
Packit aea12f
			return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit aea12f
Packit aea12f
		/* Attempt to complete handshake - we only need to receive */
Packit aea12f
		session->internals.recv_state = RECV_STATE_EARLY_START_HANDLING;
Packit aea12f
		ret = gnutls_handshake(session);
Packit aea12f
		if (ret < 0) {
Packit aea12f
			/* a temp or fatal error, make sure we reset the state
Packit aea12f
			 * so we can resume on temp errors */
Packit aea12f
			session->internals.recv_state = RECV_STATE_EARLY_START;
Packit aea12f
			return gnutls_assert_val(ret);
Packit aea12f
		}
Packit aea12f
Packit aea12f
		session->internals.recv_state = RECV_STATE_0;
Packit aea12f
		return 1;
Packit aea12f
	case RECV_STATE_DTLS_RETRANSMIT:
Packit aea12f
		ret = _dtls_retransmit(session);
Packit aea12f
		if (ret < 0)
Packit aea12f
			return gnutls_assert_val(ret);
Packit aea12f
Packit aea12f
		session->internals.recv_state = RECV_STATE_0;
Packit aea12f
Packit aea12f
		FALLTHROUGH;
Packit aea12f
	case RECV_STATE_0:
Packit aea12f
Packit aea12f
		_dtls_async_timer_check(session);
Packit aea12f
		return 1;
Packit aea12f
	default:
Packit aea12f
		return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit aea12f
	}
Packit aea12f
}
Packit aea12f
Packit aea12f
/* This function behaves exactly like read(). The only difference is
Packit aea12f
 * that it accepts the gnutls_session_t and the content_type_t of data to
Packit aea12f
 * receive (if called by the user the Content is Userdata only)
Packit aea12f
 * It is intended to receive data, under the current session.
Packit aea12f
 */
Packit aea12f
ssize_t
Packit aea12f
_gnutls_recv_int(gnutls_session_t session, content_type_t type,
Packit aea12f
		 uint8_t * data, size_t data_size, void *seq,
Packit aea12f
		 unsigned int ms)
Packit aea12f
{
Packit aea12f
	int ret;
Packit aea12f
Packit aea12f
	if ((type != GNUTLS_ALERT && type != GNUTLS_HEARTBEAT)
Packit aea12f
	    && (data_size == 0 || data == NULL))
Packit aea12f
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit aea12f
Packit aea12f
	ret = check_session_status(session, ms);
Packit aea12f
	if (ret <= 0)
Packit aea12f
		return ret;
Packit aea12f
Packit aea12f
	/* If we have enough data in the cache do not bother receiving
Packit aea12f
	 * a new packet. (in order to flush the cache)
Packit aea12f
	 */
Packit aea12f
	ret = get_data_from_buffers(session, type, data, data_size, seq);
Packit aea12f
	if (ret != 0)
Packit aea12f
		return ret;
Packit aea12f
Packit aea12f
	ret = _gnutls_recv_in_buffers(session, type, -1, ms);
Packit aea12f
	if (ret < 0 && ret != GNUTLS_E_SESSION_EOF)
Packit aea12f
		return gnutls_assert_val(ret);
Packit aea12f
Packit aea12f
	return get_data_from_buffers(session, type, data, data_size, seq);
Packit aea12f
}
Packit aea12f
Packit aea12f
/**
Packit aea12f
 * gnutls_packet_get:
Packit aea12f
 * @packet: is a #gnutls_packet_t type.
Packit aea12f
 * @data: will contain the data present in the @packet structure (may be %NULL)
Packit aea12f
 * @sequence: the 8-bytes of the packet sequence number (may be %NULL)
Packit aea12f
 *
Packit aea12f
 * This function returns the data and sequence number associated with
Packit aea12f
 * the received packet.
Packit aea12f
 *
Packit aea12f
 * Since: 3.3.5
Packit aea12f
 **/
Packit aea12f
Packit aea12f
void gnutls_packet_get(gnutls_packet_t packet, gnutls_datum_t *data, unsigned char *sequence)
Packit aea12f
{
Packit aea12f
	if (unlikely(packet == NULL)) {
Packit aea12f
		gnutls_assert();
Packit aea12f
		if (data) {
Packit aea12f
			data->data = NULL;
Packit aea12f
			data->size = 0;
Packit aea12f
			return;
Packit aea12f
		}
Packit aea12f
	}
Packit aea12f
Packit aea12f
	assert(packet != NULL);
Packit aea12f
Packit aea12f
	if (sequence) {
Packit Service 991b93
		_gnutls_write_uint64(packet->record_sequence, sequence);
Packit aea12f
	}
Packit aea12f
Packit aea12f
	if (data) {
Packit aea12f
		data->size = packet->msg.size - packet->mark;
Packit aea12f
		data->data = packet->msg.data + packet->mark;
Packit aea12f
	}
Packit aea12f
}
Packit aea12f
Packit aea12f
/**
Packit aea12f
 * gnutls_packet_deinit:
Packit aea12f
 * @packet: is a pointer to a #gnutls_packet_st structure.
Packit aea12f
 *
Packit aea12f
 * This function will deinitialize all data associated with
Packit aea12f
 * the received packet.
Packit aea12f
 *
Packit aea12f
 * Since: 3.3.5
Packit aea12f
 **/
Packit aea12f
void gnutls_packet_deinit(gnutls_packet_t packet)
Packit aea12f
{
Packit aea12f
	gnutls_free(packet);
Packit aea12f
}
Packit aea12f
Packit aea12f
/**
Packit aea12f
 * gnutls_record_discard_queued:
Packit aea12f
 * @session: is a #gnutls_session_t type.
Packit aea12f
 *
Packit Service 991b93
 * This function discards all queued to be sent packets in a DTLS session.
Packit aea12f
 * These are the packets queued after an interrupted gnutls_record_send().
Packit aea12f
 *
Packit Service 991b93
 * This function can only be used with transports where send() is
Packit Service 991b93
 * an all-or-nothing operation (e.g., UDP). When partial writes are allowed
Packit Service 991b93
 * this function will cause session errors.
Packit Service 991b93
 *
Packit aea12f
 * Returns: The number of bytes discarded.
Packit aea12f
 *
Packit aea12f
 * Since: 3.4.0
Packit aea12f
 **/
Packit aea12f
size_t
Packit aea12f
gnutls_record_discard_queued(gnutls_session_t session)
Packit aea12f
{
Packit aea12f
	size_t ret = session->internals.record_send_buffer.byte_length;
Packit aea12f
	_mbuffer_head_clear(&session->internals.record_send_buffer);
Packit aea12f
	return ret;
Packit aea12f
}
Packit aea12f
Packit aea12f
/**
Packit aea12f
 * gnutls_record_recv_packet:
Packit aea12f
 * @session: is a #gnutls_session_t type.
Packit aea12f
 * @packet: the structure that will hold the packet data
Packit aea12f
 *
Packit aea12f
 * This is a lower-level function than gnutls_record_recv() and allows
Packit aea12f
 * to directly receive the whole decrypted packet. That avoids a
Packit aea12f
 * memory copy, and is intended to be used by applications seeking high
Packit aea12f
 * performance.
Packit aea12f
 *
Packit Service 991b93
 * The received packet is accessed using gnutls_packet_get() and
Packit aea12f
 * must be deinitialized using gnutls_packet_deinit(). The returned
Packit aea12f
 * packet will be %NULL if the return value is zero (EOF).
Packit aea12f
 *
Packit aea12f
 * Returns: The number of bytes received and zero on EOF (for stream
Packit Service 991b93
 * connections).  A negative error code is returned in case of an error.
Packit aea12f
 *
Packit aea12f
 * Since: 3.3.5
Packit aea12f
 **/
Packit aea12f
ssize_t
Packit Service 991b93
gnutls_record_recv_packet(gnutls_session_t session,
Packit aea12f
			  gnutls_packet_t *packet)
Packit aea12f
{
Packit aea12f
	int ret;
Packit aea12f
Packit aea12f
	if (packet == NULL)
Packit aea12f
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit aea12f
Packit aea12f
	ret = check_session_status(session, session->internals.record_timeout_ms);
Packit aea12f
	if (ret <= 0)
Packit aea12f
		return ret;
Packit aea12f
Packit aea12f
	ret = get_packet_from_buffers(session, GNUTLS_APPLICATION_DATA, packet);
Packit aea12f
	if (ret != 0)
Packit aea12f
		return ret;
Packit aea12f
Packit aea12f
	ret = _gnutls_recv_in_buffers(session, GNUTLS_APPLICATION_DATA, -1,
Packit aea12f
				      session->internals.record_timeout_ms);
Packit aea12f
	if (ret < 0 && ret != GNUTLS_E_SESSION_EOF)
Packit aea12f
		return gnutls_assert_val(ret);
Packit aea12f
Packit aea12f
	return get_packet_from_buffers(session, GNUTLS_APPLICATION_DATA, packet);
Packit aea12f
}
Packit aea12f
Packit aea12f
static
Packit aea12f
ssize_t append_data_to_corked(gnutls_session_t session, const void *data, size_t data_size)
Packit aea12f
{
Packit aea12f
	int ret;
Packit aea12f
Packit aea12f
	if (IS_DTLS(session)) {
Packit aea12f
		if (data_size + session->internals.record_presend_buffer.length >
Packit aea12f
			gnutls_dtls_get_data_mtu(session)) {
Packit aea12f
			return gnutls_assert_val(GNUTLS_E_LARGE_PACKET);
Packit aea12f
		}
Packit aea12f
	}
Packit aea12f
Packit aea12f
	ret =
Packit aea12f
	    _gnutls_buffer_append_data(&session->internals.
Packit aea12f
				       record_presend_buffer, data,
Packit aea12f
				       data_size);
Packit aea12f
	if (ret < 0)
Packit aea12f
		return gnutls_assert_val(ret);
Packit aea12f
Packit aea12f
	return data_size;
Packit aea12f
}
Packit aea12f
Packit aea12f
/**
Packit aea12f
 * gnutls_record_send:
Packit aea12f
 * @session: is a #gnutls_session_t type.
Packit aea12f
 * @data: contains the data to send
Packit aea12f
 * @data_size: is the length of the data
Packit aea12f
 *
Packit aea12f
 * This function has the similar semantics with send().  The only
Packit aea12f
 * difference is that it accepts a GnuTLS session, and uses different
Packit aea12f
 * error codes.
Packit aea12f
 * Note that if the send buffer is full, send() will block this
Packit Service 991b93
 * function.  See the send() documentation for more information.
Packit aea12f
 *
Packit aea12f
 * You can replace the default push function which is send(), by using
Packit aea12f
 * gnutls_transport_set_push_function().
Packit aea12f
 *
Packit Service 991b93
 * If the EINTR is returned by the internal push function
Packit aea12f
 * then %GNUTLS_E_INTERRUPTED will be returned. If
Packit aea12f
 * %GNUTLS_E_INTERRUPTED or %GNUTLS_E_AGAIN is returned, you must
Packit Service 991b93
 * call this function again with the exact same parameters, or provide a
Packit Service 991b93
 * %NULL pointer for @data and 0 for @data_size, in order to write the
Packit Service 991b93
 * same data as before. If you wish to discard the previous data instead
Packit Service 991b93
 * of retrying, you must call gnutls_record_discard_queued() before
Packit Service 991b93
 * calling this function with different parameters. Note that the latter
Packit Service 991b93
 * works only on special transports (e.g., UDP).
Packit Service 991b93
 * cf. gnutls_record_get_direction().
Packit aea12f
 *
Packit aea12f
 * Note that in DTLS this function will return the %GNUTLS_E_LARGE_PACKET
Packit aea12f
 * error code if the send data exceed the data MTU value - as returned
Packit aea12f
 * by gnutls_dtls_get_data_mtu(). The errno value EMSGSIZE
Packit Service 991b93
 * also maps to %GNUTLS_E_LARGE_PACKET.
Packit aea12f
 * Note that since 3.2.13 this function can be called under cork in DTLS
Packit aea12f
 * mode, and will refuse to send data over the MTU size by returning
Packit aea12f
 * %GNUTLS_E_LARGE_PACKET.
Packit aea12f
 *
Packit aea12f
 * Returns: The number of bytes sent, or a negative error code.  The
Packit aea12f
 *   number of bytes sent might be less than @data_size.  The maximum
Packit aea12f
 *   number of bytes this function can send in a single call depends
Packit aea12f
 *   on the negotiated maximum record size.
Packit aea12f
 **/
Packit aea12f
ssize_t
Packit aea12f
gnutls_record_send(gnutls_session_t session, const void *data,
Packit aea12f
		   size_t data_size)
Packit aea12f
{
Packit aea12f
	return gnutls_record_send2(session, data, data_size, 0, 0);
Packit aea12f
}
Packit aea12f
Packit aea12f
/**
Packit aea12f
 * gnutls_record_send2:
Packit aea12f
 * @session: is a #gnutls_session_t type.
Packit aea12f
 * @data: contains the data to send
Packit aea12f
 * @data_size: is the length of the data
Packit aea12f
 * @pad: padding to be added to the record
Packit aea12f
 * @flags: must be zero
Packit aea12f
 *
Packit aea12f
 * This function is identical to gnutls_record_send() except that it
Packit aea12f
 * takes an extra argument to specify padding to be added the record.
Packit aea12f
 * To determine the maximum size of padding, use
Packit aea12f
 * gnutls_record_get_max_size() and gnutls_record_overhead_size().
Packit aea12f
 *
Packit aea12f
 * Note that in order for GnuTLS to provide constant time processing
Packit aea12f
 * of padding and data in TLS1.3, the flag %GNUTLS_SAFE_PADDING_CHECK
Packit aea12f
 * must be used in gnutls_init().
Packit aea12f
 *
Packit aea12f
 * Returns: The number of bytes sent, or a negative error code.  The
Packit aea12f
 *   number of bytes sent might be less than @data_size.  The maximum
Packit aea12f
 *   number of bytes this function can send in a single call depends
Packit aea12f
 *   on the negotiated maximum record size.
Packit aea12f
 *
Packit aea12f
 * Since: 3.6.3
Packit aea12f
 **/
Packit aea12f
ssize_t
Packit aea12f
gnutls_record_send2(gnutls_session_t session, const void *data,
Packit aea12f
		    size_t data_size, size_t pad, unsigned flags)
Packit aea12f
{
Packit aea12f
	const version_entry_st *vers = get_version(session);
Packit aea12f
	size_t max_pad = 0;
Packit aea12f
	int ret;
Packit aea12f
Packit aea12f
	if (unlikely(!session->internals.initial_negotiation_completed)) {
Packit aea12f
		/* this is to protect buggy applications from sending unencrypted
Packit aea12f
		 * data. We allow sending however, if we are in false or early start
Packit aea12f
		 * handshake state. */
Packit aea12f
		gnutls_mutex_lock(&session->internals.post_negotiation_lock);
Packit aea12f
Packit aea12f
		/* we intentionally re-check the initial_negotation_completed variable
Packit aea12f
		 * to avoid locking during normal operation of gnutls_record_send2() */
Packit aea12f
		if (!session->internals.initial_negotiation_completed &&
Packit aea12f
		    session->internals.recv_state != RECV_STATE_FALSE_START &&
Packit aea12f
		    session->internals.recv_state != RECV_STATE_FALSE_START_HANDLING &&
Packit aea12f
		    session->internals.recv_state != RECV_STATE_EARLY_START &&
Packit aea12f
		    session->internals.recv_state != RECV_STATE_EARLY_START_HANDLING &&
Packit aea12f
		    !(session->internals.hsk_flags & HSK_EARLY_DATA_IN_FLIGHT)) {
Packit aea12f
Packit aea12f
			gnutls_mutex_unlock(&session->internals.post_negotiation_lock);
Packit aea12f
			return gnutls_assert_val(GNUTLS_E_UNAVAILABLE_DURING_HANDSHAKE);
Packit aea12f
		}
Packit aea12f
		gnutls_mutex_unlock(&session->internals.post_negotiation_lock);
Packit aea12f
	}
Packit aea12f
Packit aea12f
	if (unlikely(!vers))
Packit aea12f
		return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit aea12f
Packit aea12f
	if (vers->tls13_sem)
Packit aea12f
		max_pad = gnutls_record_get_max_size(session) - gnutls_record_overhead_size(session);
Packit aea12f
Packit aea12f
	if (pad > max_pad)
Packit aea12f
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit aea12f
Packit aea12f
	switch(session->internals.rsend_state) {
Packit aea12f
		case RECORD_SEND_NORMAL:
Packit aea12f
			return _gnutls_send_tlen_int(session, GNUTLS_APPLICATION_DATA,
Packit aea12f
						     -1, EPOCH_WRITE_CURRENT, data,
Packit aea12f
						     data_size, pad, MBUFFER_FLUSH);
Packit aea12f
		case RECORD_SEND_CORKED:
Packit aea12f
		case RECORD_SEND_CORKED_TO_KU:
Packit aea12f
			return append_data_to_corked(session, data, data_size);
Packit aea12f
		case RECORD_SEND_KEY_UPDATE_1:
Packit aea12f
			_gnutls_buffer_reset(&session->internals.record_key_update_buffer);
Packit aea12f
Packit aea12f
			ret = _gnutls_buffer_append_data(&session->internals.record_key_update_buffer,
Packit aea12f
							 data, data_size);
Packit aea12f
			if (ret < 0)
Packit aea12f
				return gnutls_assert_val(ret);
Packit aea12f
Packit aea12f
			session->internals.rsend_state = RECORD_SEND_KEY_UPDATE_2;
Packit aea12f
			FALLTHROUGH;
Packit aea12f
		case RECORD_SEND_KEY_UPDATE_2:
Packit aea12f
			ret = gnutls_session_key_update(session, 0);
Packit aea12f
			if (ret < 0)
Packit aea12f
				return gnutls_assert_val(ret);
Packit aea12f
Packit aea12f
			session->internals.rsend_state = RECORD_SEND_KEY_UPDATE_3;
Packit aea12f
			FALLTHROUGH;
Packit aea12f
		case RECORD_SEND_KEY_UPDATE_3:
Packit aea12f
			ret = _gnutls_send_int(session, GNUTLS_APPLICATION_DATA,
Packit aea12f
						-1, EPOCH_WRITE_CURRENT,
Packit aea12f
						session->internals.record_key_update_buffer.data,
Packit aea12f
						session->internals.record_key_update_buffer.length,
Packit aea12f
						MBUFFER_FLUSH);
Packit aea12f
			_gnutls_buffer_clear(&session->internals.record_key_update_buffer);
Packit aea12f
			session->internals.rsend_state = RECORD_SEND_NORMAL;
Packit aea12f
			if (ret < 0)
Packit aea12f
				gnutls_assert();
Packit aea12f
Packit aea12f
			return ret;
Packit aea12f
		default:
Packit aea12f
			return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit aea12f
	}
Packit aea12f
}
Packit aea12f
Packit aea12f
/**
Packit aea12f
 * gnutls_record_send_early_data:
Packit aea12f
 * @session: is a #gnutls_session_t type.
Packit aea12f
 * @data: contains the data to send
Packit aea12f
 * @data_size: is the length of the data
Packit aea12f
 *
Packit aea12f
 * This function can be used by a client to send data early in the
Packit aea12f
 * handshake processes when resuming a session.  This is used to
Packit aea12f
 * implement a zero-roundtrip (0-RTT) mode.  It has the same semantics
Packit aea12f
 * as gnutls_record_send().
Packit aea12f
 *
Packit aea12f
 * There may be a limit to the amount of data sent as early data.  Use
Packit aea12f
 * gnutls_record_get_max_early_data_size() to check the limit.  If the
Packit aea12f
 * limit exceeds, this function returns
Packit aea12f
 * %GNUTLS_E_RECORD_LIMIT_REACHED.
Packit aea12f
 *
Packit aea12f
 * Returns: The number of bytes sent, or a negative error code.  The
Packit aea12f
 *   number of bytes sent might be less than @data_size.  The maximum
Packit aea12f
 *   number of bytes this function can send in a single call depends
Packit aea12f
 *   on the negotiated maximum record size.
Packit aea12f
 *
Packit aea12f
 * Since: 3.6.5
Packit aea12f
 **/
Packit aea12f
ssize_t gnutls_record_send_early_data(gnutls_session_t session,
Packit aea12f
				      const void *data,
Packit aea12f
				      size_t data_size)
Packit aea12f
{
Packit aea12f
	int ret;
Packit aea12f
Packit aea12f
	if (session->security_parameters.entity != GNUTLS_CLIENT)
Packit aea12f
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit aea12f
Packit aea12f
	if (xsum(session->internals.
Packit aea12f
		 early_data_presend_buffer.length,
Packit aea12f
		 data_size) >
Packit aea12f
	    session->security_parameters.max_early_data_size)
Packit aea12f
		return gnutls_assert_val(GNUTLS_E_RECORD_LIMIT_REACHED);
Packit aea12f
Packit aea12f
	ret =
Packit aea12f
	    _gnutls_buffer_append_data(&session->internals.
Packit aea12f
				       early_data_presend_buffer, data,
Packit aea12f
				       data_size);
Packit aea12f
	if (ret < 0)
Packit aea12f
		return gnutls_assert_val(ret);
Packit aea12f
Packit aea12f
	return ret;
Packit aea12f
}
Packit aea12f
Packit aea12f
/**
Packit aea12f
 * gnutls_record_recv_early_data:
Packit aea12f
 * @session: is a #gnutls_session_t type.
Packit aea12f
 * @data: the buffer that the data will be read into
Packit aea12f
 * @data_size: the number of requested bytes
Packit aea12f
 *
Packit aea12f
 * This function can be used by a searver to retrieve data sent early
Packit aea12f
 * in the handshake processes when resuming a session.  This is used
Packit aea12f
 * to implement a zero-roundtrip (0-RTT) mode.  It has the same
Packit aea12f
 * semantics as gnutls_record_recv().
Packit aea12f
 *
Packit aea12f
 * This function can be called either in a handshake hook, or after
Packit aea12f
 * the handshake is complete.
Packit aea12f
 *
Packit aea12f
 * Returns: The number of bytes received and zero when early data
Packit aea12f
 * reading is complete.  A negative error code is returned in case of
Packit aea12f
 * an error.  If no early data is received during the handshake, this
Packit aea12f
 * function returns %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE.  The
Packit aea12f
 * number of bytes received might be less than the requested
Packit aea12f
 * @data_size.
Packit aea12f
 *
Packit aea12f
 * Since: 3.6.5
Packit aea12f
 **/
Packit aea12f
ssize_t
Packit aea12f
gnutls_record_recv_early_data(gnutls_session_t session, void *data, size_t data_size)
Packit aea12f
{
Packit aea12f
	mbuffer_st *bufel;
Packit aea12f
	gnutls_datum_t msg;
Packit aea12f
	size_t length;
Packit aea12f
Packit aea12f
	if (session->security_parameters.entity != GNUTLS_SERVER)
Packit aea12f
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit aea12f
Packit aea12f
	bufel = _mbuffer_head_get_first(&session->internals.early_data_recv_buffer,
Packit aea12f
					&msg;;
Packit aea12f
	if (bufel == NULL)
Packit aea12f
		return
Packit aea12f
		    gnutls_assert_val
Packit aea12f
		    (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
Packit aea12f
Packit aea12f
	length = MIN(msg.size, data_size);
Packit aea12f
	memcpy(data, msg.data, length);
Packit aea12f
	_mbuffer_head_remove_bytes(&session->internals.early_data_recv_buffer,
Packit aea12f
				   length);
Packit aea12f
Packit aea12f
	return length;
Packit aea12f
}
Packit aea12f
Packit aea12f
/**
Packit aea12f
 * gnutls_record_cork:
Packit aea12f
 * @session: is a #gnutls_session_t type.
Packit aea12f
 *
Packit aea12f
 * If called, gnutls_record_send() will no longer send any records.
Packit aea12f
 * Any sent records will be cached until gnutls_record_uncork() is called.
Packit aea12f
 *
Packit aea12f
 * This function is safe to use with DTLS after GnuTLS 3.3.0.
Packit aea12f
 *
Packit aea12f
 * Since: 3.1.9
Packit aea12f
 **/
Packit aea12f
void gnutls_record_cork(gnutls_session_t session)
Packit aea12f
{
Packit aea12f
	session->internals.rsend_state = RECORD_SEND_CORKED;
Packit aea12f
}
Packit aea12f
Packit aea12f
/**
Packit aea12f
 * gnutls_record_uncork:
Packit aea12f
 * @session: is a #gnutls_session_t type.
Packit aea12f
 * @flags: Could be zero or %GNUTLS_RECORD_WAIT
Packit aea12f
 *
Packit aea12f
 * This resets the effect of gnutls_record_cork(), and flushes any pending
Packit aea12f
 * data. If the %GNUTLS_RECORD_WAIT flag is specified then this
Packit aea12f
 * function will block until the data is sent or a fatal error
Packit aea12f
 * occurs (i.e., the function will retry on %GNUTLS_E_AGAIN and
Packit aea12f
 * %GNUTLS_E_INTERRUPTED).
Packit aea12f
 *
Packit aea12f
 * If the flag %GNUTLS_RECORD_WAIT is not specified and the function
Packit aea12f
 * is interrupted then the %GNUTLS_E_AGAIN or %GNUTLS_E_INTERRUPTED
Packit aea12f
 * errors will be returned. To obtain the data left in the corked
Packit aea12f
 * buffer use gnutls_record_check_corked().
Packit aea12f
 *
Packit Service 991b93
 * Returns: On success the number of transmitted data is returned, or
Packit Service 991b93
 * otherwise a negative error code.
Packit aea12f
 *
Packit aea12f
 * Since: 3.1.9
Packit aea12f
 **/
Packit aea12f
int gnutls_record_uncork(gnutls_session_t session, unsigned int flags)
Packit aea12f
{
Packit aea12f
	int ret;
Packit aea12f
	ssize_t total = 0;
Packit aea12f
	record_send_state_t orig_state = session->internals.rsend_state;
Packit aea12f
Packit aea12f
	if (orig_state == RECORD_SEND_CORKED)
Packit aea12f
		session->internals.rsend_state = RECORD_SEND_NORMAL;
Packit aea12f
	else if (orig_state == RECORD_SEND_CORKED_TO_KU)
Packit aea12f
		session->internals.rsend_state = RECORD_SEND_KEY_UPDATE_1;
Packit aea12f
	else
Packit aea12f
		return 0;	/* nothing to be done */
Packit aea12f
Packit aea12f
	while (session->internals.record_presend_buffer.length > 0) {
Packit aea12f
		if (flags == GNUTLS_RECORD_WAIT) {
Packit aea12f
			do {
Packit aea12f
				ret =
Packit aea12f
				    gnutls_record_send(session,
Packit aea12f
						       session->internals.
Packit aea12f
						       record_presend_buffer.
Packit aea12f
						       data,
Packit aea12f
						       session->internals.
Packit aea12f
						       record_presend_buffer.
Packit aea12f
						       length);
Packit aea12f
			}
Packit aea12f
			while (ret < 0 && (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED));
Packit aea12f
		} else {
Packit aea12f
			ret =
Packit aea12f
			    gnutls_record_send(session,
Packit aea12f
					       session->internals.
Packit aea12f
					       record_presend_buffer.data,
Packit aea12f
					       session->internals.
Packit aea12f
					       record_presend_buffer.
Packit aea12f
					       length);
Packit aea12f
		}
Packit aea12f
		if (ret < 0)
Packit aea12f
			goto fail;
Packit aea12f
Packit aea12f
		session->internals.record_presend_buffer.data += ret;
Packit aea12f
		session->internals.record_presend_buffer.length -= ret;
Packit aea12f
		total += ret;
Packit aea12f
	}
Packit aea12f
Packit aea12f
	return total;
Packit aea12f
Packit aea12f
      fail:
Packit aea12f
	session->internals.rsend_state = orig_state;
Packit aea12f
	return ret;
Packit aea12f
}
Packit aea12f
Packit aea12f
/**
Packit aea12f
 * gnutls_record_recv:
Packit aea12f
 * @session: is a #gnutls_session_t type.
Packit aea12f
 * @data: the buffer that the data will be read into
Packit aea12f
 * @data_size: the number of requested bytes
Packit aea12f
 *
Packit aea12f
 * This function has the similar semantics with recv().  The only
Packit aea12f
 * difference is that it accepts a GnuTLS session, and uses different
Packit aea12f
 * error codes.
Packit aea12f
 * In the special case that the peer requests a renegotiation, the
Packit aea12f
 * caller will receive an error code of %GNUTLS_E_REHANDSHAKE.  In case
Packit aea12f
 * of a client, this message may be simply ignored, replied with an alert
Packit aea12f
 * %GNUTLS_A_NO_RENEGOTIATION, or replied with a new handshake,
Packit aea12f
 * depending on the client's will. A server receiving this error code
Packit aea12f
 * can only initiate a new handshake or terminate the session.
Packit aea12f
 *
Packit aea12f
 * If %EINTR is returned by the internal pull function (the default
Packit aea12f
 * is recv()) then %GNUTLS_E_INTERRUPTED will be returned.  If
Packit aea12f
 * %GNUTLS_E_INTERRUPTED or %GNUTLS_E_AGAIN is returned, you must
Packit aea12f
 * call this function again to get the data.  See also
Packit aea12f
 * gnutls_record_get_direction().
Packit aea12f
 *
Packit aea12f
 * Returns: The number of bytes received and zero on EOF (for stream
Packit Service 991b93
 * connections).  A negative error code is returned in case of an error.
Packit aea12f
 * The number of bytes received might be less than the requested @data_size.
Packit aea12f
 **/
Packit aea12f
ssize_t
Packit aea12f
gnutls_record_recv(gnutls_session_t session, void *data, size_t data_size)
Packit aea12f
{
Packit aea12f
	if (unlikely(!session->internals.initial_negotiation_completed)) {
Packit aea12f
		/* this is to protect buggy applications from sending unencrypted
Packit aea12f
		 * data. We allow sending however, if we are in false start handshake
Packit aea12f
		 * state. */
Packit aea12f
		if (session->internals.recv_state != RECV_STATE_FALSE_START &&
Packit aea12f
		    session->internals.recv_state != RECV_STATE_EARLY_START)
Packit aea12f
			return gnutls_assert_val(GNUTLS_E_UNAVAILABLE_DURING_HANDSHAKE);
Packit aea12f
	}
Packit aea12f
Packit aea12f
	return _gnutls_recv_int(session, GNUTLS_APPLICATION_DATA,
Packit aea12f
				data, data_size, NULL,
Packit aea12f
				session->internals.record_timeout_ms);
Packit aea12f
}
Packit aea12f
Packit aea12f
/**
Packit aea12f
 * gnutls_record_recv_seq:
Packit aea12f
 * @session: is a #gnutls_session_t type.
Packit aea12f
 * @data: the buffer that the data will be read into
Packit aea12f
 * @data_size: the number of requested bytes
Packit aea12f
 * @seq: is the packet's 64-bit sequence number. Should have space for 8 bytes.
Packit aea12f
 *
Packit aea12f
 * This function is the same as gnutls_record_recv(), except that
Packit aea12f
 * it returns in addition to data, the sequence number of the data.
Packit aea12f
 * This is useful in DTLS where record packets might be received
Packit aea12f
 * out-of-order. The returned 8-byte sequence number is an
Packit aea12f
 * integer in big-endian format and should be
Packit Service 991b93
 * treated as a unique message identification.
Packit aea12f
 *
Packit aea12f
 * Returns: The number of bytes received and zero on EOF.  A negative
Packit aea12f
 *   error code is returned in case of an error.  The number of bytes
Packit aea12f
 *   received might be less than @data_size.
Packit aea12f
 *
Packit aea12f
 * Since: 3.0
Packit aea12f
 **/
Packit aea12f
ssize_t
Packit aea12f
gnutls_record_recv_seq(gnutls_session_t session, void *data,
Packit aea12f
		       size_t data_size, unsigned char *seq)
Packit aea12f
{
Packit aea12f
	return _gnutls_recv_int(session, GNUTLS_APPLICATION_DATA,
Packit aea12f
				data, data_size, seq,
Packit aea12f
				session->internals.record_timeout_ms);
Packit aea12f
}
Packit aea12f
Packit aea12f
/**
Packit aea12f
 * gnutls_record_set_timeout:
Packit aea12f
 * @session: is a #gnutls_session_t type.
Packit aea12f
 * @ms: is a timeout value in milliseconds
Packit aea12f
 *
Packit aea12f
 * This function sets the receive timeout for the record layer
Packit aea12f
 * to the provided value. Use an @ms value of zero to disable
Packit aea12f
 * timeout (the default), or %GNUTLS_INDEFINITE_TIMEOUT, to
Packit aea12f
 * set an indefinite timeout.
Packit aea12f
 *
Packit aea12f
 * This function requires to set a pull timeout callback. See
Packit aea12f
 * gnutls_transport_set_pull_timeout_function().
Packit aea12f
 *
Packit aea12f
 * Since: 3.1.7
Packit aea12f
 **/
Packit aea12f
void gnutls_record_set_timeout(gnutls_session_t session, unsigned int ms)
Packit aea12f
{
Packit aea12f
	session->internals.record_timeout_ms = ms;
Packit aea12f
}