LCOV - code coverage report
Current view: top level - builds/gnutls/coverage/gnutls-git/lib - record.c (source / functions) Hit Total Coverage
Test: GnuTLS-3.6.14 Code Coverage Lines: 745 878 84.9 %
Date: 2020-10-30 04:50:48 Functions: 31 36 86.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2000-2018 Free Software Foundation, Inc.
       3             :  * Copyright (C) 2012-2018 Nikos Mavrogiannopoulos
       4             :  * Copyright (C) 2018 Red Hat, Inc.
       5             :  *
       6             :  * Author: Nikos Mavrogiannopoulos
       7             :  *
       8             :  * This file is part of GnuTLS.
       9             :  *
      10             :  * The GnuTLS is free software; you can redistribute it and/or
      11             :  * modify it under the terms of the GNU Lesser General Public License
      12             :  * as published by the Free Software Foundation; either version 2.1 of
      13             :  * the License, or (at your option) any later version.
      14             :  *
      15             :  * This library is distributed in the hope that it will be useful, but
      16             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      18             :  * Lesser General Public License for more details.
      19             :  *
      20             :  * You should have received a copy of the GNU Lesser General Public License
      21             :  * along with this program.  If not, see <https://www.gnu.org/licenses/>
      22             :  *
      23             :  */
      24             : 
      25             : /* Functions that are record layer specific, are included in this file.
      26             :  */
      27             : 
      28             : /* allocate this many bytes more when encrypting or decrypting, to
      29             :  * compensate for broken backends such as cryptodev.
      30             :  */
      31             : #define CIPHER_SLACK_SIZE 32
      32             : 
      33             : #include "gnutls_int.h"
      34             : #include "errors.h"
      35             : #include "debug.h"
      36             : #include "cipher.h"
      37             : #include "buffers.h"
      38             : #include "mbuffers.h"
      39             : #include "handshake.h"
      40             : #include "hash_int.h"
      41             : #include "cipher_int.h"
      42             : #include "algorithms.h"
      43             : #include "db.h"
      44             : #include "auth.h"
      45             : #include "num.h"
      46             : #include "record.h"
      47             : #include "datum.h"
      48             : #include "constate.h"
      49             : #include "tls13/key_update.h"
      50             : #include <ext/heartbeat.h>
      51             : #include <state.h>
      52             : #include <dtls.h>
      53             : #include <dh.h>
      54             : #include <random.h>
      55             : #include <xsize.h>
      56             : #include "locks.h"
      57             : 
      58             : struct tls_record_st {
      59             :         uint16_t header_size;
      60             :         uint8_t version[2];
      61             :         uint64_t sequence;      /* DTLS */
      62             :         uint16_t length;
      63             :         uint16_t packet_size;   /* header_size + length */
      64             :         content_type_t type;
      65             :         uint16_t epoch;         /* valid in DTLS only */
      66             : #ifdef ENABLE_SSL2
      67             :         unsigned v2:1;          /* whether an SSLv2 client hello */
      68             : #endif
      69             :         /* the data */
      70             : };
      71             : 
      72             : /**
      73             :  * gnutls_record_disable_padding:
      74             :  * @session: is a #gnutls_session_t type.
      75             :  *
      76             :  * Used to disabled padding in TLS 1.0 and above.  Normally you do not
      77             :  * need to use this function, but there are buggy clients that
      78             :  * complain if a server pads the encrypted data.  This of course will
      79             :  * disable protection against statistical attacks on the data.
      80             :  *
      81             :  * This function is defunct since 3.1.7. Random padding is disabled
      82             :  * by default unless requested using gnutls_record_send_range().
      83             :  *
      84             :  **/
      85           0 : void gnutls_record_disable_padding(gnutls_session_t session)
      86             : {
      87           0 :         return;
      88             : }
      89             : 
      90             : /**
      91             :  * gnutls_transport_set_ptr:
      92             :  * @session: is a #gnutls_session_t type.
      93             :  * @ptr: is the value.
      94             :  *
      95             :  * Used to set the first argument of the transport function (for push
      96             :  * and pull callbacks). In berkeley style sockets this function will set the
      97             :  * connection descriptor.
      98             :  *
      99             :  **/
     100             : void
     101        6059 : gnutls_transport_set_ptr(gnutls_session_t session,
     102             :                          gnutls_transport_ptr_t ptr)
     103             : {
     104        6059 :         session->internals.transport_recv_ptr = ptr;
     105        6059 :         session->internals.transport_send_ptr = ptr;
     106        6059 : }
     107             : 
     108             : /**
     109             :  * gnutls_transport_set_ptr2:
     110             :  * @session: is a #gnutls_session_t type.
     111             :  * @recv_ptr: is the value for the pull function
     112             :  * @send_ptr: is the value for the push function
     113             :  *
     114             :  * Used to set the first argument of the transport function (for push
     115             :  * and pull callbacks). In berkeley style sockets this function will set the
     116             :  * connection descriptor.  With this function you can use two different
     117             :  * pointers for receiving and sending.
     118             :  **/
     119             : void
     120           0 : gnutls_transport_set_ptr2(gnutls_session_t session,
     121             :                           gnutls_transport_ptr_t recv_ptr,
     122             :                           gnutls_transport_ptr_t send_ptr)
     123             : {
     124           0 :         session->internals.transport_send_ptr = send_ptr;
     125           0 :         session->internals.transport_recv_ptr = recv_ptr;
     126           0 : }
     127             : 
     128             : /**
     129             :  * gnutls_transport_set_int2:
     130             :  * @session: is a #gnutls_session_t type.
     131             :  * @recv_fd: is socket descriptor for the pull function
     132             :  * @send_fd: is socket descriptor for the push function
     133             :  *
     134             :  * This function sets the first argument of the transport functions,
     135             :  * such as send() and recv() for the default callbacks using the
     136             :  * system's socket API. With this function you can set two different
     137             :  * descriptors for receiving and sending.
     138             :  *
     139             :  * This function is equivalent to calling gnutls_transport_set_ptr2()
     140             :  * with the descriptors, but requires no casts.
     141             :  *
     142             :  * Since: 3.1.9
     143             :  **/
     144             : void
     145       17025 : gnutls_transport_set_int2(gnutls_session_t session,
     146             :                           int recv_fd, int send_fd)
     147             : {
     148       17025 :         session->internals.transport_send_ptr =
     149       17025 :             (gnutls_transport_ptr_t) (long) send_fd;
     150       17025 :         session->internals.transport_recv_ptr =
     151       17025 :             (gnutls_transport_ptr_t) (long) recv_fd;
     152       17025 : }
     153             : 
     154             : #if 0
     155             : /* this will be a macro */
     156             : /**
     157             :  * gnutls_transport_set_int:
     158             :  * @session: is a #gnutls_session_t type.
     159             :  * @fd: is the socket descriptor for the connection.
     160             :  *
     161             :  * This function sets the first argument of the transport function, such
     162             :  * as send() and recv() for the default callbacks using the
     163             :  * system's socket API.
     164             :  *
     165             :  * This function is equivalent to calling gnutls_transport_set_ptr()
     166             :  * with the descriptor, but requires no casts.
     167             :  *
     168             :  * Since: 3.1.9
     169             :  *
     170             :  **/
     171             : void gnutls_transport_set_int(gnutls_session_t session, int fd)
     172             : {
     173             :         session->internals.transport_recv_ptr =
     174             :             (gnutls_transport_ptr_t) (long) fd;
     175             :         session->internals.transport_send_ptr =
     176             :             (gnutls_transport_ptr_t) (long) fd;
     177             : }
     178             : #endif
     179             : 
     180             : /**
     181             :  * gnutls_transport_get_ptr:
     182             :  * @session: is a #gnutls_session_t type.
     183             :  *
     184             :  * Used to get the first argument of the transport function (like
     185             :  * PUSH and PULL).  This must have been set using
     186             :  * gnutls_transport_set_ptr().
     187             :  *
     188             :  * Returns: The first argument of the transport function.
     189             :  **/
     190           0 : gnutls_transport_ptr_t gnutls_transport_get_ptr(gnutls_session_t session)
     191             : {
     192           0 :         return session->internals.transport_recv_ptr;
     193             : }
     194             : 
     195             : /**
     196             :  * gnutls_transport_get_ptr2:
     197             :  * @session: is a #gnutls_session_t type.
     198             :  * @recv_ptr: will hold the value for the pull function
     199             :  * @send_ptr: will hold the value for the push function
     200             :  *
     201             :  * Used to get the arguments of the transport functions (like PUSH
     202             :  * and PULL).  These should have been set using
     203             :  * gnutls_transport_set_ptr2().
     204             :  **/
     205             : void
     206           0 : gnutls_transport_get_ptr2(gnutls_session_t session,
     207             :                           gnutls_transport_ptr_t * recv_ptr,
     208             :                           gnutls_transport_ptr_t * send_ptr)
     209             : {
     210             : 
     211           0 :         *recv_ptr = session->internals.transport_recv_ptr;
     212           0 :         *send_ptr = session->internals.transport_send_ptr;
     213           0 : }
     214             : 
     215             : /**
     216             :  * gnutls_transport_get_int2:
     217             :  * @session: is a #gnutls_session_t type.
     218             :  * @recv_int: will hold the value for the pull function
     219             :  * @send_int: will hold the value for the push function
     220             :  *
     221             :  * Used to get the arguments of the transport functions (like PUSH
     222             :  * and PULL).  These should have been set using
     223             :  * gnutls_transport_set_int2().
     224             :  *
     225             :  * Since: 3.1.9
     226             :  **/
     227             : void
     228           0 : gnutls_transport_get_int2(gnutls_session_t session,
     229             :                           int *recv_int, int *send_int)
     230             : {
     231             : 
     232           0 :         *recv_int = (long) session->internals.transport_recv_ptr;
     233           0 :         *send_int = (long) session->internals.transport_send_ptr;
     234           0 : }
     235             : 
     236             : /**
     237             :  * gnutls_transport_get_int:
     238             :  * @session: is a #gnutls_session_t type.
     239             :  *
     240             :  * Used to get the first argument of the transport function (like
     241             :  * PUSH and PULL).  This must have been set using
     242             :  * gnutls_transport_set_int().
     243             :  *
     244             :  * Returns: The first argument of the transport function.
     245             :  *
     246             :  * Since: 3.1.9
     247             :  **/
     248         268 : int gnutls_transport_get_int(gnutls_session_t session)
     249             : {
     250         268 :         return (long) session->internals.transport_recv_ptr;
     251             : }
     252             : 
     253             : /**
     254             :  * gnutls_bye:
     255             :  * @session: is a #gnutls_session_t type.
     256             :  * @how: is an integer
     257             :  *
     258             :  * Terminates the current TLS/SSL connection. The connection should
     259             :  * have been initiated using gnutls_handshake().  @how should be one
     260             :  * of %GNUTLS_SHUT_RDWR, %GNUTLS_SHUT_WR.
     261             :  *
     262             :  * In case of %GNUTLS_SHUT_RDWR the TLS session gets
     263             :  * terminated and further receives and sends will be disallowed.  If
     264             :  * the return value is zero you may continue using the underlying
     265             :  * transport layer. %GNUTLS_SHUT_RDWR sends an alert containing a close
     266             :  * request and waits for the peer to reply with the same message.
     267             :  *
     268             :  * In case of %GNUTLS_SHUT_WR the TLS session gets terminated
     269             :  * and further sends will be disallowed. In order to reuse the
     270             :  * connection you should wait for an EOF from the peer.
     271             :  * %GNUTLS_SHUT_WR sends an alert containing a close request.
     272             :  *
     273             :  * Note that not all implementations will properly terminate a TLS
     274             :  * connection.  Some of them, usually for performance reasons, will
     275             :  * terminate only the underlying transport layer, and thus not
     276             :  * distinguishing between a malicious party prematurely terminating
     277             :  * the connection and normal termination.
     278             :  *
     279             :  * This function may also return %GNUTLS_E_AGAIN or
     280             :  * %GNUTLS_E_INTERRUPTED; cf.  gnutls_record_get_direction().
     281             :  *
     282             :  * Returns: %GNUTLS_E_SUCCESS on success, or an error code, see
     283             :  *   function documentation for entire semantics.
     284             :  **/
     285      120139 : int gnutls_bye(gnutls_session_t session, gnutls_close_request_t how)
     286             : {
     287      120139 :         int ret = 0;
     288             : 
     289      120139 :         switch (BYE_STATE) {
     290       12493 :         case BYE_STATE0:
     291       12493 :                 ret = _gnutls_io_write_flush(session);
     292       12493 :                 BYE_STATE = BYE_STATE0;
     293       12493 :                 if (ret < 0) {
     294           1 :                         gnutls_assert();
     295           1 :                         return ret;
     296             :                 }
     297       12508 :                 FALLTHROUGH;
     298             :         case BYE_STATE1:
     299       12508 :                 ret =
     300       12508 :                     gnutls_alert_send(session, GNUTLS_AL_WARNING,
     301             :                                       GNUTLS_A_CLOSE_NOTIFY);
     302       12508 :                 BYE_STATE = BYE_STATE1;
     303       12508 :                 if (ret < 0) {
     304         135 :                         gnutls_assert();
     305         135 :                         return ret;
     306             :                 }
     307      120003 :                 FALLTHROUGH;
     308             :         case BYE_STATE2:
     309      120003 :                 BYE_STATE = BYE_STATE2;
     310      120003 :                 if (how == GNUTLS_SHUT_RDWR) {
     311      110034 :                         do {
     312      220068 :                                 ret =
     313      110034 :                                     _gnutls_recv_int(session, GNUTLS_ALERT,
     314             :                                                      NULL, 0, NULL,
     315             :                                                      session->internals.
     316             :                                                      record_timeout_ms);
     317             :                         }
     318      110034 :                         while (ret == GNUTLS_E_GOT_APPLICATION_DATA);
     319             : 
     320      108943 :                         if (ret >= 0)
     321         884 :                                 session->internals.may_not_read = 1;
     322             : 
     323      108943 :                         if (ret < 0) {
     324      108059 :                                 gnutls_assert();
     325      108059 :                                 return ret;
     326             :                         }
     327             :                 }
     328       11944 :                 BYE_STATE = BYE_STATE2;
     329             : 
     330       11944 :                 break;
     331           0 :         default:
     332           0 :                 gnutls_assert();
     333             :                 return GNUTLS_E_INTERNAL_ERROR;
     334             :         }
     335             : 
     336       11944 :         BYE_STATE = BYE_STATE0;
     337             : 
     338       11944 :         session->internals.may_not_write = 1;
     339       11944 :         return 0;
     340             : }
     341             : 
     342        3881 : inline static void session_unresumable(gnutls_session_t session)
     343             : {
     344        3881 :         session->internals.resumable = RESUME_FALSE;
     345             : }
     346             : 
     347             : /* returns 0 if session is valid
     348             :  */
     349    29025200 : inline static int session_is_valid(gnutls_session_t session)
     350             : {
     351    29025200 :         if (session->internals.invalid_connection != 0)
     352             :                 return GNUTLS_E_INVALID_SESSION;
     353             : 
     354             :         return 0;
     355             : }
     356             : 
     357             : /* Copies the record version into the headers. The
     358             :  * version must have 2 bytes at least.
     359             :  */
     360             : inline static int
     361     2514720 : copy_record_version(gnutls_session_t session,
     362             :                     gnutls_handshake_description_t htype,
     363             :                     uint8_t version[2])
     364             : {
     365     2514720 :         const version_entry_st *lver;
     366             : 
     367     2514720 :         lver = get_version(session);
     368     2514720 :         if (session->internals.initial_negotiation_completed ||
     369        3710 :             htype != GNUTLS_HANDSHAKE_CLIENT_HELLO ||
     370        3710 :             session->internals.default_record_version[0] == 0) {
     371             : 
     372     2511010 :                 if (unlikely(lver == NULL))
     373           0 :                         return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
     374             : 
     375     2511010 :                 if (lver->tls13_sem) {
     376      462906 :                         version[0] = 0x03;
     377      462906 :                         version[1] = 0x03;
     378             :                 } else {
     379     2048100 :                         version[0] = lver->major;
     380     2048100 :                         version[1] = lver->minor;
     381             :                 }
     382             :         } else {
     383        3710 :                 version[0] = session->internals.default_record_version[0];
     384        3710 :                 version[1] = session->internals.default_record_version[1];
     385             :         }
     386             : 
     387             :         return 0;
     388             : }
     389             : 
     390             : /* Increments the sequence value
     391             :  */
     392             : inline static int
     393     5697620 : sequence_increment(gnutls_session_t session, uint64_t * value)
     394             : {
     395     5697620 :         uint64_t snmax = UINT64_C(0xffffffffffffffff);
     396             : 
     397     5697620 :         if (IS_DTLS(session)) {
     398       19304 :                 uint64_t mask;
     399             : 
     400       19304 :                 snmax = UINT64_C(0xffffffffffff);
     401       19304 :                 mask = snmax;
     402             : 
     403       19304 :                 if ((*value & mask) == snmax)
     404             :                         return -1;
     405             : 
     406       19304 :                 *value = ((*value & mask) + 1) | (*value & ~mask);
     407             :         } else {
     408     5678320 :                 if (*value == snmax)
     409             :                         return -1;
     410             : 
     411     5678320 :                 (*value)++;
     412             :         }
     413             : 
     414             :         return 0;
     415             : }
     416             : 
     417             : /* This function behaves exactly like write(). The only difference is
     418             :  * that it accepts, the gnutls_session_t and the content_type_t of data to
     419             :  * send (if called by the user the Content is specific)
     420             :  * It is intended to transfer data, under the current session.
     421             :  *
     422             :  * @type: The content type to send
     423             :  * @htype: If this is a handshake message then the handshake type
     424             :  * @epoch_rel: %EPOCH_READ_* or %EPOCH_WRITE_*
     425             :  * @data: the data to be sent
     426             :  * @data_size: the size of the @data
     427             :  * @min_pad: the minimum required padding
     428             :  * @mflags: zero or %MBUFFER_FLUSH
     429             :  *
     430             :  * Oct 30 2001: Removed capability to send data more than MAX_RECORD_SIZE.
     431             :  * This makes the function much easier to read, and more error resistant
     432             :  * (there were cases were the old function could mess everything up).
     433             :  * --nmav
     434             :  *
     435             :  * This function may accept a NULL pointer for data, and 0 for size, if
     436             :  * and only if the previous send was interrupted for some reason.
     437             :  *
     438             :  */
     439             : ssize_t
     440     2514790 : _gnutls_send_tlen_int(gnutls_session_t session, content_type_t type,
     441             :                       gnutls_handshake_description_t htype,
     442             :                       unsigned int epoch_rel, const void *_data,
     443             :                       size_t data_size, size_t min_pad,
     444             :                       unsigned int mflags)
     445             : {
     446     2514790 :         mbuffer_st *bufel;
     447     2514790 :         ssize_t cipher_size;
     448     2514790 :         int retval, ret;
     449     2514790 :         int send_data_size;
     450     2514790 :         uint8_t *headers;
     451     2514790 :         int header_size;
     452     2514790 :         const uint8_t *data = _data;
     453     2514790 :         record_parameters_st *record_params;
     454     2514790 :         size_t max_send_size;
     455     2514790 :         record_state_st *record_state;
     456     2514790 :         const version_entry_st *vers = get_version(session);
     457             : 
     458     2514790 :         ret = _gnutls_epoch_get(session, epoch_rel, &record_params);
     459     2514790 :         if (ret < 0)
     460           0 :                 return gnutls_assert_val(ret);
     461             : 
     462             :         /* Safeguard against processing data with an incomplete cipher state. */
     463     2514790 :         if (!record_params->initialized)
     464           0 :                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
     465             : 
     466     2514790 :         record_state = &record_params->write;
     467             : 
     468             :         /* Do not allow null pointer if the send buffer is empty.
     469             :          * If the previous send was interrupted then a null pointer is
     470             :          * ok, and means to resume.
     471             :          */
     472     2514790 :         if (session->internals.record_send_buffer.byte_length == 0 &&
     473     2453970 :             (data_size == 0 && _data == NULL)) {
     474           0 :                 gnutls_assert();
     475           0 :                 return GNUTLS_E_INVALID_REQUEST;
     476             :         }
     477             : 
     478     2514790 :         if (type != GNUTLS_ALERT)       /* alert messages are sent anyway */
     479     2497080 :                 if (session_is_valid(session)
     480     2497080 :                     || session->internals.may_not_write != 0) {
     481           0 :                         gnutls_assert();
     482           0 :                         return GNUTLS_E_INVALID_SESSION;
     483             :                 }
     484             : 
     485     2514790 :         max_send_size = max_record_send_size(session, record_params);
     486             : 
     487     2514790 :         if (data_size > max_send_size) {
     488         762 :                 if (IS_DTLS(session))
     489          58 :                         return gnutls_assert_val(GNUTLS_E_LARGE_PACKET);
     490             : 
     491         704 :                 send_data_size = max_send_size;
     492             :         } else
     493     2514030 :                 send_data_size = data_size;
     494             : 
     495             :         /* Only encrypt if we don't have data to send
     496             :          * from the previous run. - probably interrupted.
     497             :          */
     498     2514730 :         if (mflags != 0
     499     2415970 :             && session->internals.record_send_buffer.byte_length > 0) {
     500          16 :                 ret = _gnutls_io_write_flush(session);
     501          16 :                 if (ret > 0)
     502           9 :                         cipher_size = ret;
     503             :                 else
     504             :                         cipher_size = 0;
     505             : 
     506          16 :                 retval = session->internals.record_send_buffer_user_size;
     507             :         } else {
     508     2514720 :                 if (unlikely((send_data_size == 0 && min_pad == 0)))
     509           1 :                         return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
     510             : 
     511             :                 /* now proceed to packet encryption
     512             :                  */
     513     2514720 :                 cipher_size = MAX_RECORD_SEND_SIZE(session);
     514             : 
     515     5029430 :                 bufel = _mbuffer_alloc_align16(cipher_size + CIPHER_SLACK_SIZE,
     516             :                         get_total_headers2(session, record_params));
     517     2514720 :                 if (bufel == NULL)
     518           0 :                         return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
     519             : 
     520     2514720 :                 headers = _mbuffer_get_uhead_ptr(bufel);
     521     2514720 :                 if (vers->tls13_sem && record_params->cipher->id != GNUTLS_CIPHER_NULL)
     522      451078 :                         headers[0] = GNUTLS_APPLICATION_DATA;
     523             :                 else
     524     2063640 :                         headers[0] = type;
     525             : 
     526             :                 /* Use the default record version, if it is
     527             :                  * set. */
     528     2514720 :                 ret = copy_record_version(session, htype, &headers[1]);
     529     2514720 :                 if (ret < 0)
     530           0 :                         return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
     531             : 
     532             :                 /* Adjust header length and add sequence for DTLS */
     533     2514720 :                 if (IS_DTLS(session))
     534        9960 :                         _gnutls_write_uint64(record_state->sequence_number, &headers[3]);
     535             : 
     536     2514720 :                 _gnutls_record_log
     537             :                     ("REC[%p]: Preparing Packet %s(%d) with length: %d and min pad: %d\n",
     538             :                      session, _gnutls_packet2str(type), type,
     539             :                      (int) data_size, (int) min_pad);
     540             : 
     541     2514720 :                 header_size = RECORD_HEADER_SIZE(session);
     542     2514720 :                 _mbuffer_set_udata_size(bufel, cipher_size);
     543     2514720 :                 _mbuffer_set_uhead_size(bufel, header_size);
     544             : 
     545     2514720 :                 ret =
     546     2514720 :                     _gnutls_encrypt(session,
     547             :                                     data, send_data_size, min_pad,
     548             :                                     bufel, type, record_params);
     549     2514720 :                 if (ret <= 0) {
     550           2 :                         gnutls_assert();
     551           2 :                         if (ret == 0)
     552           0 :                                 ret = GNUTLS_E_ENCRYPTION_FAILED;
     553           2 :                         gnutls_free(bufel);
     554           2 :                         return ret;     /* error */
     555             :                 }
     556             : 
     557     2514710 :                 cipher_size = _mbuffer_get_udata_size(bufel);
     558     2514710 :                 retval = send_data_size;
     559     2514710 :                 session->internals.record_send_buffer_user_size =
     560             :                     send_data_size;
     561             : 
     562             :                 /* increase sequence number
     563             :                  */
     564     5029430 :                 if (sequence_increment
     565             :                     (session, &record_state->sequence_number) != 0) {
     566           0 :                         session_invalidate(session);
     567           0 :                         gnutls_free(bufel);
     568           0 :                         return
     569           0 :                             gnutls_assert_val
     570             :                             (GNUTLS_E_RECORD_LIMIT_REACHED);
     571             :                 }
     572             : 
     573     2514710 :                 ret = _gnutls_io_write_buffered(session, bufel, mflags);
     574             :         }
     575             : 
     576     2514730 :         if (ret != cipher_size) {
     577             :                 /* If we have sent any data then just return
     578             :                  * the error value. Do not invalidate the session.
     579             :                  */
     580         241 :                 if (ret < 0 && gnutls_error_is_fatal(ret) == 0)
     581          24 :                         return gnutls_assert_val(ret);
     582             : 
     583         217 :                 if (ret > 0)
     584           0 :                         ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
     585             : 
     586         217 :                 session_unresumable(session);
     587         217 :                 session->internals.may_not_write = 1;
     588         313 :                 return gnutls_assert_val(ret);
     589             :         }
     590             : 
     591     2514480 :         session->internals.record_send_buffer_user_size = 0;
     592             : 
     593     2514480 :         _gnutls_record_log
     594             :             ("REC[%p]: Sent Packet[%ld] %s(%d) in epoch %d and length: %d\n",
     595             :              session, (unsigned long)(record_state->sequence_number),
     596             :              _gnutls_packet2str(type), type, (int) record_params->epoch,
     597             :              (int) cipher_size);
     598             : 
     599     2514480 :         if (vers->tls13_sem && !(session->internals.flags & GNUTLS_NO_AUTO_REKEY) &&
     600      462830 :             !(record_params->cipher->flags & GNUTLS_CIPHER_FLAG_NO_REKEY)) {
     601      393295 :                 if (unlikely((record_state->sequence_number & UINT64_C(0xffffff)) == UINT64_C(0xfffffd))) {
     602             :                         /* After we have sent 2^24 messages, mark the session
     603             :                          * as needing a key update. */
     604           2 :                         session->internals.rsend_state = RECORD_SEND_KEY_UPDATE_1;
     605             :                 }
     606             :         }
     607             : 
     608     2514480 :         return retval;
     609             : }
     610             : 
     611             : inline static int
     612     3189080 : check_recv_type(gnutls_session_t session, content_type_t recv_type)
     613             : {
     614     3189080 :         switch (recv_type) {
     615             :         case GNUTLS_CHANGE_CIPHER_SPEC:
     616             :         case GNUTLS_ALERT:
     617             :         case GNUTLS_HANDSHAKE:
     618             :         case GNUTLS_HEARTBEAT:
     619             :         case GNUTLS_APPLICATION_DATA:
     620             :                 return 0;
     621         325 :         default:
     622         325 :                 gnutls_assert();
     623         325 :                 _gnutls_audit_log(session,
     624             :                                   "Received record packet of unknown type %u\n",
     625             :                                   (unsigned int) recv_type);
     626         325 :                 return GNUTLS_E_UNEXPECTED_PACKET;
     627             :         }
     628             : 
     629             : }
     630             : 
     631             : 
     632             : /* Checks if there are pending data in the record buffers. If there are
     633             :  * then it copies the data.
     634             :  */
     635             : static int
     636     5475330 : get_data_from_buffers(gnutls_session_t session, content_type_t type,
     637             :               uint8_t * data, int data_size, void *seq)
     638             : {
     639     5475330 :         if ((type == GNUTLS_APPLICATION_DATA ||
     640     5475330 :              type == GNUTLS_HANDSHAKE || type == GNUTLS_CHANGE_CIPHER_SPEC)
     641     5364420 :             && _gnutls_record_buffer_get_size(session) > 0) {
     642     2405840 :                 int ret;
     643     2405840 :                 ret =
     644     2405840 :                     _gnutls_record_buffer_get(type, session, data,
     645             :                                               data_size, seq);
     646     2405840 :                 if (ret < 0) {
     647          17 :                         if (IS_DTLS(session)) {
     648           6 :                                 if (ret == GNUTLS_E_UNEXPECTED_PACKET) {
     649           6 :                                         ret = GNUTLS_E_AGAIN;
     650             :                                 }
     651             :                         }
     652          17 :                         gnutls_assert();
     653          17 :                         return ret;
     654             :                 }
     655             : 
     656             :                 return ret;
     657             :         }
     658             : 
     659             :         return 0;
     660             : }
     661             : 
     662             : /* Checks and retrieves any pending data in the application data record buffers.
     663             :  */
     664             : static int
     665          84 : get_packet_from_buffers(gnutls_session_t session, content_type_t type,
     666             :                      gnutls_packet_t *packet)
     667             : {
     668          84 :         if (_gnutls_record_buffer_get_size(session) > 0) {
     669          21 :                 int ret;
     670          21 :                 ret =
     671          21 :                         _gnutls_record_buffer_get_packet(type, session, packet);
     672          21 :                 if (ret < 0) {
     673           0 :                         if (IS_DTLS(session)) {
     674           0 :                                 if (ret == GNUTLS_E_UNEXPECTED_PACKET) {
     675           0 :                                         ret = GNUTLS_E_AGAIN;
     676             :                                 }
     677             :                         }
     678           0 :                         gnutls_assert();
     679           0 :                         return ret;
     680             :                 }
     681             : 
     682             :                 return ret;
     683             :         }
     684             : 
     685          63 :         *packet = NULL;
     686          63 :         return 0;
     687             : }
     688             : 
     689             : 
     690             : 
     691             : /* Here we check if the advertized version is the one we
     692             :  * negotiated in the handshake.
     693             :  */
     694             : inline static int
     695     3188750 : record_check_version(gnutls_session_t session,
     696             :                      gnutls_handshake_description_t htype,
     697             :                      uint8_t version[2])
     698             : {
     699     3188750 :         const version_entry_st *vers = get_version(session);
     700     3188750 :         int diff = 0;
     701             : 
     702     3188750 :         if (vers->tls13_sem) {
     703             :                 /* TLS 1.3 requires version to be 0x0303 */
     704      515934 :                 if (version[0] != 0x03 || version[1] != 0x03)
     705       80038 :                         diff = 1;
     706             :         } else {
     707     2672820 :                 if (vers->major != version[0] || vers->minor != version[1])
     708      447212 :                         diff = 1;
     709             :         }
     710             : 
     711     3188750 :         if (!IS_DTLS(session)) {
     712     3177740 :                 if (htype == GNUTLS_HANDSHAKE_CLIENT_HELLO ||
     713     3177740 :                     htype == GNUTLS_HANDSHAKE_HELLO_RETRY_REQUEST ||
     714             :                     htype == GNUTLS_HANDSHAKE_SERVER_HELLO) {
     715      724921 :                         if (version[0] != 3) {
     716          20 :                                 gnutls_assert();
     717          20 :                                 _gnutls_record_log
     718             :                                     ("REC[%p]: INVALID VERSION PACKET: (%d) %d.%d\n",
     719             :                                      session, htype, version[0],
     720             :                                      version[1]);
     721          20 :                                 return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
     722             :                         }
     723     2452820 :                 } else if (diff != 0) {
     724             :                         /* Reject record packets that have a different version than the
     725             :                          * one negotiated. Note that this version is not protected by any
     726             :                          * mac. I don't really think that this check serves any purpose.
     727             :                          */
     728          39 :                         gnutls_assert();
     729          39 :                         _gnutls_record_log
     730             :                             ("REC[%p]: INVALID VERSION PACKET: (%d) %d.%d\n",
     731             :                              session, htype, version[0], version[1]);
     732             : 
     733          39 :                         return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
     734             :                 }
     735             :         } else {                /* DTLS */
     736             : 
     737             :                 /* In DTLS the only information we have here is whether we
     738             :                  * expect a handshake message or not.
     739             :                  */
     740       11008 :                 if (htype == (gnutls_handshake_description_t) - 1) {
     741        7843 :                         if (diff) {
     742             :                                 /* Reject record packets that have a different version than the
     743             :                                  * one negotiated. Note that this version is not protected by any
     744             :                                  * mac. I don't really think that this check serves any purpose.
     745             :                                  */
     746           4 :                                 gnutls_assert();
     747           4 :                                 _gnutls_record_log
     748             :                                     ("REC[%p]: INVALID VERSION PACKET: (%d) %d.%d\n",
     749             :                                      session, htype, version[0],
     750             :                                      version[1]);
     751             : 
     752           4 :                                 return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
     753             :                         }
     754        3165 :                 } else if (vers->id > GNUTLS_DTLS1_0 && version[0] > 254) {
     755           0 :                         gnutls_assert();
     756           0 :                         _gnutls_record_log
     757             :                             ("REC[%p]: INVALID DTLS VERSION PACKET: (%d) %d.%d\n",
     758             :                              session, htype, version[0], version[1]);
     759           0 :                         return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
     760        3165 :                 } else if (vers->id == GNUTLS_DTLS0_9 && version[0] > 1) {
     761           0 :                         gnutls_assert();
     762           0 :                         _gnutls_record_log
     763             :                             ("REC[%p]: INVALID DTLS VERSION PACKET: (%d) %d.%d\n",
     764             :                              session, htype, version[0], version[1]);
     765           0 :                         return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
     766             :                 }
     767             :         }
     768             : 
     769             :         return 0;
     770             : }
     771             : 
     772             : static int
     773          63 : recv_hello_request(gnutls_session_t session, void *data,
     774             :                    uint32_t data_size)
     775             : {
     776          63 :         uint8_t type;
     777             : 
     778          63 :         if (session->security_parameters.entity == GNUTLS_SERVER)
     779          11 :                 return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
     780             : 
     781          56 :         if (data_size < 1)
     782           0 :                 return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
     783             : 
     784          56 :         if (session->internals.handshake_in_progress)
     785           4 :                 return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
     786             : 
     787          52 :         type = ((uint8_t *) data)[0];
     788          52 :         if (type == GNUTLS_HANDSHAKE_HELLO_REQUEST) {
     789          52 :                 if (IS_DTLS(session))
     790           4 :                         session->internals.dtls.hsk_read_seq++;
     791          52 :                 if (session->internals.flags & GNUTLS_AUTO_REAUTH) {
     792           2 :                         session->internals.recv_state = RECV_STATE_REHANDSHAKE;
     793           2 :                         return GNUTLS_E_AGAIN;
     794             :                 } else {
     795             :                         return GNUTLS_E_REHANDSHAKE;
     796             :                 }
     797             :         } else {
     798           0 :                 gnutls_assert();
     799           0 :                 return GNUTLS_E_UNEXPECTED_PACKET;
     800             :         }
     801             : }
     802             : 
     803             : /* This function will check if the received record type is
     804             :  * the one we actually expect and adds it to the proper
     805             :  * buffer. The bufel will be deinitialized after calling
     806             :  * this function, even if it fails.
     807             :  */
     808             : static int
     809     3182790 : record_add_to_buffers(gnutls_session_t session,
     810             :                       struct tls_record_st *recv, content_type_t type,
     811             :                       gnutls_handshake_description_t htype,
     812             :                       uint64_t seq, mbuffer_st * bufel)
     813             : {
     814             : 
     815     3182790 :         int ret;
     816     3182790 :         const version_entry_st *ver = get_version(session);
     817             : 
     818     3182790 :         if ((recv->type == type)
     819     3174190 :             && (type == GNUTLS_APPLICATION_DATA ||
     820     3174190 :                 type == GNUTLS_CHANGE_CIPHER_SPEC ||
     821             :                 type == GNUTLS_HANDSHAKE)) {
     822     3173310 :                 if (bufel->msg.size == 0) {
     823           9 :                         if (type == GNUTLS_APPLICATION_DATA) {
     824             :                                 /* this is needed to distinguish an empty
     825             :                                  * message and EOF */
     826           9 :                                 ret = GNUTLS_E_AGAIN;
     827           9 :                                 goto cleanup;
     828             :                         } else {
     829           0 :                                 ret =
     830           0 :                                     gnutls_assert_val
     831             :                                     (GNUTLS_E_UNEXPECTED_PACKET);
     832           0 :                                 goto unexpected_packet;
     833             :                         }
     834             :                 }
     835             : 
     836             :                 /* application data cannot be inserted between (async) handshake
     837             :                  * messages */
     838     3173300 :                 if (type == GNUTLS_APPLICATION_DATA &&
     839     2396440 :                     (session->internals.handshake_recv_buffer_size != 0 ||
     840     2396440 :                      session->internals.handshake_header_recv_buffer.length != 0)) {
     841           0 :                         ret = gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
     842           0 :                         goto unexpected_packet;
     843             :                 }
     844             : 
     845     3173300 :                 _gnutls_record_buffer_put(session, type, seq, bufel);
     846             : 
     847             :                 /* if we received application data as expected then we
     848             :                  * deactivate the async timer */
     849     3173300 :                 _dtls_async_timer_delete(session);
     850             :         } else {
     851             :                 /* if the expected type is different than the received
     852             :                  */
     853        9483 :                 switch (recv->type) {
     854        7596 :                 case GNUTLS_ALERT:
     855        7596 :                         if (bufel->msg.size < 2) {
     856          16 :                                 ret =
     857          16 :                                     gnutls_assert_val
     858             :                                     (GNUTLS_E_UNEXPECTED_PACKET);
     859          16 :                                 goto unexpected_packet;
     860             :                         }
     861             : 
     862        7580 :                         _gnutls_record_log
     863             :                             ("REC[%p]: Alert[%d|%d] - %s - was received\n",
     864             :                              session, bufel->msg.data[0],
     865             :                              bufel->msg.data[1],
     866             :                              gnutls_alert_get_name((int) bufel->msg.
     867             :                                                    data[1]));
     868             : 
     869        7580 :                         if (!session->internals.initial_negotiation_completed &&
     870        1714 :                             session->internals.handshake_in_progress && STATE == STATE0) { /* handshake hasn't started */
     871           5 :                                 ret = gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
     872           5 :                                 goto unexpected_packet;
     873             :                         }
     874             : 
     875        7575 :                         session->internals.last_alert = bufel->msg.data[1];
     876             : 
     877             :                         /* if close notify is received and
     878             :                          * the alert is not fatal
     879             :                          */
     880        7575 :                         if (bufel->msg.data[1] == GNUTLS_A_CLOSE_NOTIFY
     881        5876 :                             && bufel->msg.data[0] != GNUTLS_AL_FATAL) {
     882             :                                 /* If we have been expecting for an alert do
     883             :                                  */
     884        5870 :                                 session->internals.read_eof = 1;
     885        5870 :                                 ret = GNUTLS_E_SESSION_EOF;
     886        5870 :                                 goto cleanup;
     887             :                         } else {
     888             :                                 /* if the alert is FATAL or WARNING
     889             :                                  * return the appropriate message
     890             :                                  */
     891        1705 :                                 gnutls_assert();
     892        1705 :                                 ret = GNUTLS_E_WARNING_ALERT_RECEIVED;
     893        1705 :                                 if ((ver && ver->tls13_sem) || bufel->msg.data[0] == GNUTLS_AL_FATAL) {
     894         178 :                                         session_unresumable(session);
     895         178 :                                         session_invalidate(session);
     896         178 :                                         ret =
     897        1705 :                                             gnutls_assert_val
     898             :                                             (GNUTLS_E_FATAL_ALERT_RECEIVED);
     899             :                                 }
     900        1705 :                                 goto cleanup;
     901             :                         }
     902         114 :                         break;
     903             : 
     904         114 :                 case GNUTLS_CHANGE_CIPHER_SPEC:
     905         114 :                         if (!(IS_DTLS(session))) {
     906          99 :                                 ret = gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
     907          99 :                                 goto cleanup;
     908             :                         }
     909             : 
     910          15 :                         _gnutls_record_buffer_put(session, recv->type, seq,
     911             :                                                   bufel);
     912             : 
     913          15 :                         break;
     914             : 
     915             : #ifdef ENABLE_HEARTBEAT
     916          18 :                 case GNUTLS_HEARTBEAT:
     917          18 :                         ret = _gnutls_heartbeat_handle(session, bufel);
     918          18 :                         goto cleanup;
     919             : #endif
     920             : 
     921        1126 :                 case GNUTLS_APPLICATION_DATA:
     922        1126 :                         if (session->internals.
     923             :                             initial_negotiation_completed == 0) {
     924          20 :                                 ret =
     925          20 :                                     gnutls_assert_val
     926             :                                     (GNUTLS_E_UNEXPECTED_PACKET);
     927          20 :                                 goto unexpected_packet;
     928             :                         }
     929             : 
     930             :                         /* In TLS1.3 post-handshake authentication allow application
     931             :                          * data error code. */
     932        1106 :                         if ((ver && ver->tls13_sem) && type == GNUTLS_HANDSHAKE &&
     933         561 :                             htype == GNUTLS_HANDSHAKE_CERTIFICATE_PKT &&
     934             :                             session->internals.initial_negotiation_completed) {
     935           9 :                                 _gnutls_record_buffer_put(session, recv->type,
     936             :                                                           seq, bufel);
     937           9 :                                 return
     938           9 :                                     gnutls_assert_val
     939             :                                     (GNUTLS_E_GOT_APPLICATION_DATA);
     940             :                         }
     941             : 
     942             :                         /* The got_application data is only returned
     943             :                          * if expecting client hello (for rehandshake
     944             :                          * reasons). Otherwise it is an unexpected packet
     945             :                          */
     946        1097 :                         if (type == GNUTLS_ALERT
     947           6 :                             || ((htype == GNUTLS_HANDSHAKE_SERVER_HELLO ||
     948           6 :                                  htype == GNUTLS_HANDSHAKE_CLIENT_HELLO ||
     949           6 :                                  htype == GNUTLS_HANDSHAKE_HELLO_RETRY_REQUEST)
     950           5 :                                 && type == GNUTLS_HANDSHAKE)) {
     951             :                                 /* even if data is unexpected put it into the buffer */
     952        1096 :                                 _gnutls_record_buffer_put(session, recv->type,
     953             :                                                           seq, bufel);
     954        1096 :                                 return
     955        1096 :                                     gnutls_assert_val
     956             :                                     (GNUTLS_E_GOT_APPLICATION_DATA);
     957             :                         } else {
     958           1 :                                 ret =
     959           1 :                                     gnutls_assert_val
     960             :                                     (GNUTLS_E_UNEXPECTED_PACKET);
     961           1 :                                 goto unexpected_packet;
     962             :                         }
     963             : 
     964         629 :                         break;
     965             : 
     966         629 :                 case GNUTLS_HANDSHAKE:
     967             :                         /* In DTLS we might receive a handshake replay from the peer to indicate
     968             :                          * the our last TLS handshake messages were not received.
     969             :                          */
     970         629 :                         if (IS_DTLS(session)) {
     971         159 :                                 if (type == GNUTLS_CHANGE_CIPHER_SPEC) {
     972          87 :                                         ret =
     973          87 :                                             gnutls_assert_val
     974             :                                             (GNUTLS_E_UNEXPECTED_PACKET);
     975          87 :                                         goto unexpected_packet;
     976             :                                 }
     977             : 
     978         140 :                                 if (_dtls_is_async(session)
     979          68 :                                     && _dtls_async_timer_active(session)) {
     980          68 :                                         if (session->security_parameters.
     981             :                                             entity == GNUTLS_SERVER
     982          39 :                                             && bufel->htype ==
     983             :                                             GNUTLS_HANDSHAKE_CLIENT_HELLO)
     984             :                                         {
     985             :                                                 /* client requested rehandshake. Delete the timer */
     986           6 :                                                 _dtls_async_timer_delete
     987             :                                                     (session);
     988             :                                         } else {
     989          62 :                                                 session->internals.
     990          62 :                                                     recv_state =
     991             :                                                     RECV_STATE_DTLS_RETRANSMIT;
     992          62 :                                                 ret =
     993          62 :                                                     _dtls_retransmit
     994             :                                                     (session);
     995          62 :                                                 if (ret == 0) {
     996          62 :                                                         session->internals.
     997          62 :                                                             recv_state =
     998             :                                                             RECV_STATE_0;
     999          62 :                                                         ret =
    1000          62 :                                                             gnutls_assert_val
    1001             :                                                             (GNUTLS_E_AGAIN);
    1002          62 :                                                         goto unexpected_packet;
    1003             :                                                 }
    1004           0 :                                                 goto cleanup;
    1005             :                                         }
    1006             :                                 }
    1007             :                         }
    1008             : 
    1009             :                         /* retrieve async handshake messages */
    1010         480 :                         if (ver && ver->tls13_sem) {
    1011         381 :                                 _gnutls_record_buffer_put(session, recv->type, seq, bufel);
    1012             : 
    1013         381 :                                 ret = _gnutls13_recv_async_handshake(session);
    1014         381 :                                 if (ret < 0)
    1015           9 :                                         return gnutls_assert_val(ret);
    1016             : 
    1017             :                                 /* bufel is now accounted */
    1018             :                                 return GNUTLS_E_AGAIN;
    1019             :                         }
    1020             : 
    1021             :                         /* This is legal if HELLO_REQUEST is received - and we are a client.
    1022             :                          * If we are a server, a client may initiate a renegotiation at any time.
    1023             :                          */
    1024          99 :                         if (session->security_parameters.entity ==
    1025             :                             GNUTLS_SERVER
    1026          43 :                             && session->internals.handshake_in_progress == 0
    1027          37 :                             && bufel->htype ==
    1028             :                             GNUTLS_HANDSHAKE_CLIENT_HELLO) {
    1029          36 :                                 gnutls_assert();
    1030          36 :                                 _gnutls_record_buffer_put(session,
    1031             :                                                               recv->type,
    1032             :                                                               seq, bufel);
    1033          36 :                                 return GNUTLS_E_REHANDSHAKE;
    1034             :                         }
    1035             : 
    1036             :                         /* If we are already in a handshake then a Hello
    1037             :                          * Request is illegal. But here we don't really care
    1038             :                          * since this message will never make it up here.
    1039             :                          */
    1040             : 
    1041             :                         /* So we accept it, if it is a Hello. If not, this will
    1042             :                          * fail and trigger flight retransmissions after some time. */
    1043          63 :                         ret =
    1044         126 :                             recv_hello_request(session,
    1045          63 :                                                bufel->msg.data,
    1046             :                                                bufel->msg.size);
    1047          63 :                         goto unexpected_packet;
    1048           0 :                 default:
    1049             : 
    1050           0 :                         _gnutls_record_log
    1051             :                             ("REC[%p]: Received unexpected packet %d (%s) expecting %d (%s)\n",
    1052             :                              session, recv->type,
    1053             :                              _gnutls_packet2str(recv->type), type,
    1054             :                              _gnutls_packet2str(type));
    1055             : 
    1056           0 :                         gnutls_assert();
    1057           0 :                         ret = GNUTLS_E_UNEXPECTED_PACKET;
    1058           0 :                         goto unexpected_packet;
    1059             :                 }
    1060             :         }
    1061             : 
    1062             :         return 0;
    1063             : 
    1064         254 :  unexpected_packet:
    1065             : 
    1066         254 :         if (IS_DTLS(session) && ret != GNUTLS_E_REHANDSHAKE) {
    1067         149 :                 _mbuffer_xfree(&bufel);
    1068         298 :                 RETURN_DTLS_EAGAIN_OR_TIMEOUT(session, ret);
    1069             :         }
    1070             : 
    1071         105 :  cleanup:
    1072        7806 :         _mbuffer_xfree(&bufel);
    1073             :         return ret;
    1074             : 
    1075             : }
    1076             : 
    1077             : 
    1078             : /* Checks the record headers and returns the length, version and
    1079             :  * content type.
    1080             :  */
    1081             : static void
    1082     3189080 : record_read_headers(gnutls_session_t session,
    1083             :                     uint8_t headers[MAX_RECORD_HEADER_SIZE],
    1084             :                     content_type_t type,
    1085             :                     gnutls_handshake_description_t htype,
    1086             :                     struct tls_record_st *record)
    1087             : {
    1088             : 
    1089             :         /* Read the first two bytes to determine if this is a
    1090             :          * version 2 message
    1091             :          */
    1092             : 
    1093             : #ifdef ENABLE_SSL2
    1094     3189080 :         if (htype == GNUTLS_HANDSHAKE_CLIENT_HELLO
    1095     3189080 :             && type == GNUTLS_HANDSHAKE && headers[0] > 127
    1096      161698 :             && !(IS_DTLS(session))) {
    1097             : 
    1098             :                 /* if msb set and expecting handshake message
    1099             :                  * it should be SSL 2 hello
    1100             :                  */
    1101      161698 :                 record->version[0] = 3;      /* assume SSL 3.0 */
    1102      161698 :                 record->version[1] = 0;
    1103             : 
    1104      161698 :                 record->length = (((headers[0] & 0x7f) << 8)) | headers[1];
    1105             : 
    1106             :                 /* SSL 2.0 headers */
    1107      161698 :                 record->header_size = record->packet_size = 2;
    1108      161698 :                 record->type = GNUTLS_HANDSHAKE;     /* we accept only v2 client hello
    1109             :                                                          */
    1110             : 
    1111             :                 /* in order to assist the handshake protocol.
    1112             :                  * V2 compatibility is a mess.
    1113             :                  */
    1114      161698 :                 record->v2 = 1;
    1115      161698 :                 record->epoch = 0;
    1116      161698 :                 memset(&record->sequence, 0, sizeof(record->sequence));
    1117             : 
    1118      161698 :                 _gnutls_record_log
    1119             :                     ("REC[%p]: SSL 2.0 %s packet received. Length: %d\n",
    1120             :                      session, _gnutls_packet2str(record->type),
    1121             :                      record->length);
    1122             : 
    1123             :         } else
    1124             : #endif
    1125             :         {
    1126             :                 /* dtls version 1.0 and TLS version 1.x */
    1127             : #ifdef ENABLE_SSL2
    1128     3027390 :                 record->v2 = 0;
    1129             : #endif
    1130             : 
    1131     3027390 :                 record->type = headers[0];
    1132     3027390 :                 record->version[0] = headers[1];
    1133     3027390 :                 record->version[1] = headers[2];
    1134             : 
    1135     3027390 :                 if (IS_DTLS(session)) {
    1136       11014 :                         record->sequence = _gnutls_read_uint64(&headers[3]);
    1137       11014 :                         record->length = _gnutls_read_uint16(&headers[11]);
    1138       11014 :                         record->epoch = record->sequence >> 48;
    1139             :                 } else {
    1140     3016370 :                         memset(&record->sequence, 0,
    1141             :                                sizeof(record->sequence));
    1142     3016370 :                         record->length = _gnutls_read_uint16(&headers[3]);
    1143     3016370 :                         record->epoch = session->security_parameters.epoch_read;
    1144             :                 }
    1145             : 
    1146     3027390 :                 _gnutls_record_log
    1147             :                     ("REC[%p]: SSL %d.%d %s packet received. Epoch %d, length: %d\n",
    1148             :                      session, (int) record->version[0],
    1149             :                      (int) record->version[1],
    1150             :                      _gnutls_packet2str(record->type), (int) record->epoch,
    1151             :                      record->length);
    1152             : 
    1153             :         }
    1154             : 
    1155     3189080 :         record->packet_size += record->length;
    1156     3189080 : }
    1157             : 
    1158             : 
    1159    23464200 : static int recv_headers(gnutls_session_t session,
    1160             :                         record_parameters_st *record_params,
    1161             :                         content_type_t type,
    1162             :                         gnutls_handshake_description_t htype,
    1163             :                         struct tls_record_st *record, unsigned int *ms)
    1164             : {
    1165    23464200 :         int ret;
    1166    23464200 :         gnutls_datum_t raw;     /* raw headers */
    1167             :         /* Read the headers.
    1168             :          */
    1169    46928500 :         record->header_size = record->packet_size =
    1170    23464200 :             RECORD_HEADER_SIZE(session);
    1171             : 
    1172    46928500 :         ret =
    1173    23464200 :             _gnutls_io_read_buffered(session, record->header_size, -1, ms);
    1174    23464200 :         if (ret != record->header_size) {
    1175    20275200 :                 if (ret < 0 && gnutls_error_is_fatal(ret) == 0)
    1176             :                         return ret;
    1177             : 
    1178        1890 :                 if (ret > 0)
    1179             :                         ret = GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
    1180        1890 :                 else if (ret == 0)
    1181        1779 :                         ret = GNUTLS_E_PREMATURE_TERMINATION;
    1182             : 
    1183        1997 :                 return gnutls_assert_val(ret);
    1184             :         }
    1185             : 
    1186     6378170 :         ret = _mbuffer_linearize_align16(&session->internals.record_recv_buffer,
    1187             :                 get_total_headers2(session, record_params));
    1188     3189080 :         if (ret < 0)
    1189           0 :                 return gnutls_assert_val(ret);
    1190             : 
    1191     3189080 :         _mbuffer_head_get_first(&session->internals.record_recv_buffer,
    1192             :                                 &raw);
    1193     6367150 :         if (raw.size < RECORD_HEADER_SIZE(session))
    1194           0 :                 return
    1195           0 :                     gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
    1196             : 
    1197     3189080 :         record_read_headers(session, raw.data, type, htype, record);
    1198             : 
    1199             :         /* Check if the DTLS epoch is valid */
    1200     3189080 :         if (IS_DTLS(session)) {
    1201       22022 :                 if (_gnutls_epoch_is_valid(session, record->epoch) == 0) {
    1202           6 :                         _gnutls_audit_log(session,
    1203             :                                           "Discarded message[%lu] with invalid epoch %u.\n",
    1204             :                                           (unsigned long)record->sequence,
    1205           6 :                                           (unsigned int) (record->sequence >> 48));
    1206           6 :                         gnutls_assert();
    1207             :                         /* doesn't matter, just a fatal error */
    1208           6 :                         return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
    1209             :                 }
    1210             :         }
    1211             : 
    1212             :         /* Here we check if the Type of the received packet is
    1213             :          * ok.
    1214             :          */
    1215     3189080 :         if ((ret = check_recv_type(session, record->type)) < 0)
    1216         325 :                 return gnutls_assert_val(ret);
    1217             : 
    1218             :         /* Here we check if the advertized version is the one we
    1219             :          * negotiated in the handshake.
    1220             :          */
    1221     6377510 :         if ((ret =
    1222     3188750 :              record_check_version(session, htype, record->version)) < 0)
    1223          63 :                 return gnutls_assert_val(ret);
    1224             : 
    1225     3945540 :         if (record->length == 0 || record->length > max_record_recv_size(session)) {
    1226         123 :                 _gnutls_audit_log
    1227             :                     (session, "Received packet with illegal length: %u (max: %u)\n",
    1228             :                      (unsigned int) record->length, (unsigned)max_record_recv_size(session));
    1229             : 
    1230          78 :                 if (record->length == 0) {
    1231             :                         /* Empty, unencrypted records are always unexpected. */
    1232          43 :                         if (record_params->cipher->id == GNUTLS_CIPHER_NULL)
    1233          17 :                                 return
    1234          17 :                                     gnutls_assert_val
    1235             :                                     (GNUTLS_E_UNEXPECTED_PACKET);
    1236             : 
    1237          28 :                         return gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
    1238             :                 }
    1239          35 :                 return
    1240          35 :                     gnutls_assert_val(GNUTLS_E_RECORD_OVERFLOW);
    1241             :         }
    1242             : 
    1243     3188610 :         _gnutls_record_log
    1244             :             ("REC[%p]: Expected Packet %s(%d)\n", session,
    1245             :              _gnutls_packet2str(type), type);
    1246     3188610 :         _gnutls_record_log
    1247             :             ("REC[%p]: Received Packet %s(%d) with length: %d\n", session,
    1248             :              _gnutls_packet2str(record->type), record->type,
    1249             :              record->length);
    1250             : 
    1251             : 
    1252             :         return 0;
    1253             : }
    1254             : 
    1255             : /* @ms: is the number of milliseconds to wait for data. Use zero for indefinite.
    1256             :  *
    1257             :  * This will receive record layer packets and add them to
    1258             :  * application_data_buffer and handshake_data_buffer.
    1259             :  *
    1260             :  * If the htype is not -1 then handshake timeouts
    1261             :  * will be enforced.
    1262             :  */
    1263             : ssize_t
    1264    23461500 : _gnutls_recv_in_buffers(gnutls_session_t session, content_type_t type,
    1265             :                         gnutls_handshake_description_t htype,
    1266             :                         unsigned int ms)
    1267             : {
    1268    23461500 :         uint64_t packet_sequence;
    1269    23461500 :         gnutls_datum_t ciphertext;
    1270    23461500 :         mbuffer_st *bufel = NULL, *decrypted = NULL;
    1271    23461500 :         gnutls_datum_t t;
    1272    23461500 :         int ret;
    1273    23461500 :         unsigned int n_retries = 0;
    1274    23461500 :         record_parameters_st *record_params;
    1275    23461500 :         record_state_st *record_state;
    1276    23461500 :         struct tls_record_st record;
    1277    23461500 :         const version_entry_st *vers = get_version(session);
    1278             : 
    1279        2730 :  begin:
    1280             : 
    1281    23464200 :         if (n_retries > DEFAULT_MAX_EMPTY_RECORDS) {
    1282           0 :                 gnutls_assert();
    1283           0 :                 return GNUTLS_E_TOO_MANY_EMPTY_PACKETS;
    1284             :         }
    1285             : 
    1286    23464200 :         if (session->internals.read_eof != 0) {
    1287             :                 /* if we have already read an EOF
    1288             :                  */
    1289             :                 return 0;
    1290    23464200 :         } else if (session_is_valid(session) != 0
    1291    23464200 :                    || session->internals.may_not_read != 0)
    1292           1 :                 return gnutls_assert_val(GNUTLS_E_INVALID_SESSION);
    1293             : 
    1294             :         /* get the record state parameters */
    1295    23464200 :         ret =
    1296    23464200 :             _gnutls_epoch_get(session, EPOCH_READ_CURRENT, &record_params);
    1297    23464200 :         if (ret < 0)
    1298           0 :                 return gnutls_assert_val(ret);
    1299             : 
    1300             :         /* Safeguard against processing data with an incomplete cipher state. */
    1301    23464200 :         if (!record_params->initialized)
    1302           0 :                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
    1303             : 
    1304    23464200 :         record_state = &record_params->read;
    1305             : 
    1306             :         /* receive headers */
    1307    31708400 :         ret = recv_headers(session, record_params, type, htype, &record, (!(session->internals.flags & GNUTLS_NONBLOCK))?&ms:0);
    1308    23464200 :         if (ret < 0) {
    1309    20275600 :                 ret = gnutls_assert_val_fatal(ret);
    1310    20275600 :                 goto recv_error;
    1311             :         }
    1312             : 
    1313     3188610 :         if (IS_DTLS(session))
    1314       10983 :                 packet_sequence = record.sequence;
    1315             :         else
    1316     3177630 :                 packet_sequence = record_state->sequence_number;
    1317             : 
    1318             :         /* Read the packet data and insert it to record_recv_buffer.
    1319             :          */
    1320     6377220 :         ret =
    1321     3188610 :             _gnutls_io_read_buffered(session, record.packet_size,
    1322     3188610 :                                      record.type, (!(session->internals.flags & GNUTLS_NONBLOCK))?&ms:0);
    1323     3188610 :         if (ret != record.packet_size) {
    1324         454 :                 gnutls_assert();
    1325         454 :                 goto recv_error;
    1326             :         }
    1327             : 
    1328             :         /* ok now we are sure that we have read all the data - so
    1329             :          * move on !
    1330             :          */
    1331     6376320 :         ret = _mbuffer_linearize_align16(&session->internals.record_recv_buffer,
    1332             :                 get_total_headers2(session, record_params));
    1333     3188160 :         if (ret < 0)
    1334           0 :                 return gnutls_assert_val(ret);
    1335             : 
    1336     6376320 :         bufel =
    1337     3188160 :             _mbuffer_head_get_first(&session->internals.record_recv_buffer,
    1338             :                                     NULL);
    1339     3188160 :         if (bufel == NULL)
    1340           0 :                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
    1341             : 
    1342     3188160 :         if (vers && vers->tls13_sem && record.type == GNUTLS_CHANGE_CIPHER_SPEC) {
    1343             :                 /* if the CCS has value other than 0x01, or arrives
    1344             :                  * after Finished, abort the connection */
    1345        2620 :                 if (record.length != 1 ||
    1346        2620 :                     *((uint8_t *) _mbuffer_get_udata_ptr(bufel) +
    1347        2620 :                       record.header_size) != 0x01 ||
    1348        2619 :                     !session->internals.handshake_in_progress)
    1349           5 :                         return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
    1350             : 
    1351        2616 :                 _gnutls_read_log("discarding change cipher spec in TLS1.3\n");
    1352             :                 /* we use the same mechanism to retry as when
    1353             :                  * receiving multiple empty TLS packets */
    1354        5232 :                 bufel =
    1355        2616 :                     _mbuffer_head_pop_first(&session->internals.
    1356             :                                             record_recv_buffer);
    1357        2616 :                 _mbuffer_xfree(&bufel);
    1358        2616 :                 n_retries++;
    1359        2616 :                 goto begin;
    1360             :         }
    1361             : 
    1362             :         /* We allocate the maximum possible to allow few compressed bytes to expand to a
    1363             :          * full record. Moreover we add space for any pad and the MAC (in case
    1364             :          * they are encrypted).
    1365             :          */
    1366     3185540 :         ret = max_decrypted_size(session) + MAX_PAD_SIZE + MAX_HASH_SIZE;
    1367     3185540 :         decrypted = _mbuffer_alloc_align16(ret, 0);
    1368     3185540 :         if (decrypted == NULL)
    1369           0 :                 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
    1370             : 
    1371     3185540 :         _mbuffer_set_udata_size(decrypted, ret);
    1372     3185540 :         ciphertext.data =
    1373     3185540 :             (uint8_t *) _mbuffer_get_udata_ptr(bufel) + record.header_size;
    1374     3185540 :         ciphertext.size = record.length;
    1375             : 
    1376             :         /* decrypt the data we got.
    1377             :          */
    1378     3185540 :         t.data = _mbuffer_get_udata_ptr(decrypted);
    1379     3185540 :         t.size = _mbuffer_get_udata_size(decrypted);
    1380     3185540 :         ret =
    1381     3185540 :             _gnutls_decrypt(session, &ciphertext, &t,
    1382             :                             &record.type, record_params, packet_sequence);
    1383     3185540 :         if (ret >= 0)
    1384     3182980 :                 _mbuffer_set_udata_size(decrypted, ret);
    1385             : 
    1386     3185540 :         _mbuffer_head_remove_bytes(&session->internals.record_recv_buffer,
    1387     3185540 :                                    record.header_size + record.length);
    1388             : 
    1389     3185540 :         if (session->security_parameters.entity == GNUTLS_SERVER &&
    1390     2152970 :             session->internals.hsk_flags & HSK_EARLY_DATA_IN_FLIGHT) {
    1391          29 :                 if (session->internals.hsk_flags & HSK_EARLY_DATA_ACCEPTED) {
    1392           9 :                         if (ret < 0 ||
    1393             :                             /* early data must always be encrypted, treat it
    1394             :                              * as decryption failure if otherwise */
    1395           8 :                             record_params->cipher->id == GNUTLS_CIPHER_NULL) {
    1396           1 :                                 _gnutls_record_log
    1397             :                                         ("REC[%p]: failed to decrypt early data, in epoch %d\n",
    1398             :                                          session,
    1399             :                                                 record_params->epoch);
    1400           1 :                                 ret = GNUTLS_E_DECRYPTION_FAILED;
    1401           1 :                                 goto sanity_check_error;
    1402           8 :                         } else if (record.type == GNUTLS_APPLICATION_DATA) {
    1403           4 :                                 size_t decrypted_length =
    1404           4 :                                         _mbuffer_get_udata_size(decrypted);
    1405           4 :                                 _gnutls_record_log
    1406             :                                         ("REC[%p]: decrypted early data with length: %d, in epoch %d\n",
    1407             :                                          session,
    1408             :                                          (int) decrypted_length,
    1409             :                                          record_params->epoch);
    1410           4 :                                 if (decrypted_length >
    1411           4 :                                     session->security_parameters.max_early_data_size -
    1412           4 :                                     session->internals.early_data_received) {
    1413           0 :                                         _gnutls_record_log
    1414             :                                                 ("REC[%p]: max_early_data_size exceeded\n",
    1415             :                                                  session);
    1416           0 :                                         ret = GNUTLS_E_UNEXPECTED_PACKET;
    1417           0 :                                         goto sanity_check_error;
    1418             :                                 }
    1419             : 
    1420           4 :                                 _mbuffer_enqueue(&session->internals.early_data_recv_buffer, decrypted);
    1421           4 :                                 session->internals.early_data_received +=
    1422             :                                         decrypted_length;
    1423             : 
    1424             :                                 /* Increase sequence number. We do both for TLS and DTLS, since in
    1425             :                                  * DTLS we also rely on that number (roughly) since it may get reported
    1426             :                                  * to application via gnutls_record_get_state().
    1427             :                                  */
    1428           8 :                                 if (sequence_increment(session, &record_state->sequence_number) != 0) {
    1429           0 :                                         session_invalidate(session);
    1430           0 :                                         gnutls_assert();
    1431           0 :                                         ret = GNUTLS_E_RECORD_LIMIT_REACHED;
    1432           0 :                                         goto sanity_check_error;
    1433             :                                 }
    1434             : 
    1435             :                                 /* decrypted is now accounted */
    1436           4 :                                 return GNUTLS_E_AGAIN;
    1437             :                         }
    1438             :                 } else {
    1439             :                         /* We do not accept early data: skip decryption
    1440             :                          * failure up to max_early_data_size. Otherwise,
    1441             :                          * if the record is properly decrypted, treat it as
    1442             :                          * the start of client's second flight.
    1443             :                          */
    1444          20 :                         if (record.type == GNUTLS_APPLICATION_DATA &&
    1445           2 :                             (ret < 0 ||
    1446             :                              /* early data must always be encrypted, treat it
    1447             :                               * as decryption failure if otherwise */
    1448           2 :                              record_params->cipher->id == GNUTLS_CIPHER_NULL)) {
    1449          11 :                                 if (record.length >
    1450          11 :                                     session->security_parameters.max_early_data_size -
    1451          11 :                                     session->internals.early_data_received) {
    1452           0 :                                         _gnutls_record_log
    1453             :                                                 ("REC[%p]: max_early_data_size exceeded\n",
    1454             :                                                  session);
    1455           0 :                                         ret = GNUTLS_E_UNEXPECTED_PACKET;
    1456           0 :                                         goto sanity_check_error;
    1457             :                                 }
    1458             : 
    1459          11 :                                 _gnutls_record_log("REC[%p]: Discarded early data[%lu] due to invalid decryption, length: %u\n",
    1460             :                                                    session,
    1461             :                                                    (unsigned long)packet_sequence,
    1462             :                                                    (unsigned int)
    1463             :                                                    record.length);
    1464          11 :                                 session->internals.early_data_received += record.length;
    1465             :                                 /* silently discard received data */
    1466          11 :                                 _mbuffer_xfree(&decrypted);
    1467          20 :                                 return gnutls_assert_val(GNUTLS_E_AGAIN);
    1468             :                         } else {
    1469           9 :                                 session->internals.hsk_flags &= ~HSK_EARLY_DATA_IN_FLIGHT;
    1470             :                         }
    1471             :                 }
    1472             :         }
    1473             : 
    1474     3185520 :         if (ret < 0) {
    1475        2547 :                 gnutls_assert();
    1476        2547 :                 _gnutls_audit_log(session,
    1477             :                                   "Discarded message[%lu] due to invalid decryption\n",
    1478             :                                   (unsigned long)packet_sequence);
    1479        2547 :                 goto sanity_check_error;
    1480             :         }
    1481             : 
    1482     3182980 :         if (IS_DTLS(session)) {
    1483             :                 /* check for duplicates. We check after the message
    1484             :                  * is processed and authenticated to avoid someone
    1485             :                  * messing with our windows. */
    1486        9412 :                 if (likely(!(session->internals.flags & GNUTLS_NO_REPLAY_PROTECTION))) {
    1487        9412 :                         ret = _dtls_record_check(record_params, packet_sequence);
    1488        9412 :                         if (ret < 0) {
    1489          68 :                                 _gnutls_record_log
    1490             :                                     ("REC[%p]: Discarded duplicate message[%u.%lu]: %s\n",
    1491             :                                      session,
    1492             :                                      (unsigned int) (record.sequence >> 48),
    1493             :                                      (unsigned long) (packet_sequence),
    1494             :                                      _gnutls_packet2str(record.type));
    1495          68 :                                 goto sanity_check_error;
    1496             :                         }
    1497             :                 }
    1498             : 
    1499        9344 :                 _gnutls_record_log
    1500             :                     ("REC[%p]: Decrypted Packet[%u.%lu] %s(%d) with length: %d\n",
    1501             :                      session,
    1502             :                      (unsigned int) (record.sequence >> 48),
    1503             :                      (unsigned long) packet_sequence,
    1504             :                      _gnutls_packet2str(record.type), record.type,
    1505             :                      (int) _mbuffer_get_udata_size(decrypted));
    1506             : 
    1507             :                 /* store the last valid sequence number. We don't use that internally but
    1508             :                  * callers of gnutls_record_get_state() could take advantage of it. */
    1509        9344 :                 record_state->sequence_number = record.sequence;
    1510             :         } else {
    1511     3173560 :                 _gnutls_record_log
    1512             :                     ("REC[%p]: Decrypted Packet[%lu] %s(%d) with length: %d\n",
    1513             :                      session,
    1514             :                      (unsigned long) packet_sequence,
    1515             :                      _gnutls_packet2str(record.type), record.type,
    1516             :                      (int) _mbuffer_get_udata_size(decrypted));
    1517             : 
    1518             :         }
    1519             : 
    1520             :         /* Increase sequence number. We do both for TLS and DTLS, since in
    1521             :          * DTLS we also rely on that number (roughly) since it may get reported
    1522             :          * to application via gnutls_record_get_state().
    1523             :          */
    1524     6365810 :         if (sequence_increment(session, &record_state->sequence_number) != 0) {
    1525           0 :                 session_invalidate(session);
    1526           0 :                 gnutls_assert();
    1527           0 :                 ret = GNUTLS_E_RECORD_LIMIT_REACHED;
    1528           0 :                 goto sanity_check_error;
    1529             :         }
    1530             : 
    1531             : /* (originally for) TLS 1.0 CBC protection.
    1532             :  * Actually this code is called if we just received
    1533             :  * an empty packet. An empty TLS packet is usually
    1534             :  * sent to protect some vulnerabilities in the CBC mode.
    1535             :  * In that case we go to the beginning and start reading
    1536             :  * the next packet.
    1537             :  */
    1538     3182910 :         if (_mbuffer_get_udata_size(decrypted) == 0 &&
    1539             :             /* Under TLS 1.3, there are only AEAD ciphers and this
    1540             :              * logic is meaningless. Moreover, the implementation need
    1541             :              * to send correct alert upon receiving empty messages in
    1542             :              * certain occasions. Skip this and leave
    1543             :              * record_add_to_buffers() to handle the empty
    1544             :              * messages. */
    1545         134 :             !(vers && vers->tls13_sem)) {
    1546         114 :                 _mbuffer_xfree(&decrypted);
    1547         114 :                 n_retries++;
    1548         114 :                 goto begin;
    1549             :         }
    1550             : 
    1551     3183510 :         if (_mbuffer_get_udata_size(decrypted) > max_decrypted_size(session)) {
    1552           4 :                 _gnutls_audit_log
    1553             :                     (session, "Received packet with illegal length: %u\n",
    1554             :                      (unsigned int) ret);
    1555             : 
    1556           4 :                 ret = gnutls_assert_val(GNUTLS_E_RECORD_OVERFLOW);
    1557           4 :                 goto sanity_check_error;
    1558             :         }
    1559             : 
    1560             : #ifdef ENABLE_SSL2
    1561     3182790 :         if (record.v2) {
    1562      161601 :                 decrypted->htype = GNUTLS_HANDSHAKE_CLIENT_HELLO_V2;
    1563             :         } else
    1564             : #endif
    1565             :         {
    1566     3021190 :                 uint8_t *p = _mbuffer_get_udata_ptr(decrypted);
    1567     3021190 :                 decrypted->htype = p[0];
    1568             :         }
    1569             : 
    1570     3182790 :         ret =
    1571     3182790 :             record_add_to_buffers(session, &record, type, htype,
    1572             :                                   packet_sequence, decrypted);
    1573             : 
    1574             :         /* decrypted is now either deinitialized or buffered somewhere else */
    1575             : 
    1576     3182790 :         if (ret < 0)
    1577        9558 :                 return gnutls_assert_val(ret);
    1578             : 
    1579     3173310 :         return ret;
    1580             : 
    1581          31 :  discard:
    1582          31 :         session->internals.dtls.packets_dropped++;
    1583             : 
    1584             :         /* discard the whole received fragment. */
    1585          62 :         bufel =
    1586          31 :             _mbuffer_head_pop_first(&session->internals.
    1587             :                                     record_recv_buffer);
    1588          31 :         _mbuffer_xfree(&bufel);
    1589          31 :         return gnutls_assert_val(GNUTLS_E_AGAIN);
    1590             : 
    1591        2620 :  sanity_check_error:
    1592        2620 :         if (IS_DTLS(session)) {
    1593        1639 :                 session->internals.dtls.packets_dropped++;
    1594        1639 :                 ret = gnutls_assert_val(GNUTLS_E_AGAIN);
    1595        1639 :                 goto cleanup;
    1596             :         }
    1597             : 
    1598         981 :         session_unresumable(session);
    1599         981 :         session_invalidate(session);
    1600             : 
    1601        2620 :  cleanup:
    1602        2620 :         _mbuffer_xfree(&decrypted);
    1603        2620 :         return ret;
    1604             : 
    1605    20276100 :  recv_error:
    1606    20276100 :         if (ret < 0
    1607    20275900 :             && (gnutls_error_is_fatal(ret) == 0
    1608        2372 :                 || ret == GNUTLS_E_TIMEDOUT))
    1609    20273600 :                 return ret;
    1610             : 
    1611        2539 :         if (type == GNUTLS_ALERT) {     /* we were expecting close notify */
    1612           3 :                 session_invalidate(session);
    1613           3 :                 gnutls_assert();
    1614           3 :                 return 0;
    1615             :         }
    1616             : 
    1617        2536 :         if (IS_DTLS(session) && (ret == GNUTLS_E_DECRYPTION_FAILED ||
    1618          31 :                 ret == GNUTLS_E_UNSUPPORTED_VERSION_PACKET ||
    1619           6 :                 ret == GNUTLS_E_UNEXPECTED_PACKET_LENGTH ||
    1620           6 :                 ret == GNUTLS_E_RECORD_OVERFLOW ||
    1621           0 :                 ret == GNUTLS_E_UNEXPECTED_PACKET ||
    1622           0 :                 ret == GNUTLS_E_ERROR_IN_FINISHED_PACKET ||
    1623             :                 ret == GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET)) {
    1624          31 :                 goto discard;
    1625             :         }
    1626             : 
    1627        2505 :         session_invalidate(session);
    1628        2505 :         session_unresumable(session);
    1629             : 
    1630        2505 :         if (ret == 0)
    1631             :                 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
    1632             :         else
    1633        2329 :                 return ret;
    1634             : }
    1635             : 
    1636             : /* Returns a value greater than zero (>= 0) if buffers should be checked
    1637             :  * for data. */
    1638             : static ssize_t
    1639     3063840 : check_session_status(gnutls_session_t session, unsigned ms)
    1640             : {
    1641     3063840 :         int ret;
    1642             : 
    1643     3063840 :         if (session->internals.read_eof != 0) {
    1644             :                 /* if we have already read an EOF
    1645             :                  */
    1646             :                 return 0;
    1647     3063840 :         } else if (session_is_valid(session) != 0
    1648     3063830 :                    || session->internals.may_not_read != 0) {
    1649          13 :                 gnutls_assert();
    1650          13 :                 return GNUTLS_E_INVALID_SESSION;
    1651             :         }
    1652             : 
    1653     3063830 :         switch (session->internals.recv_state) {
    1654           0 :         case RECV_STATE_REAUTH:
    1655           0 :                 session->internals.recv_state = RECV_STATE_0;
    1656             : 
    1657           0 :                 ret = gnutls_reauth(session, 0);
    1658           0 :                 if (ret < 0) {
    1659             :                         /* a temp or fatal error, make sure we reset the state
    1660             :                          * so we can resume on temp errors */
    1661           0 :                         session->internals.recv_state = RECV_STATE_REAUTH;
    1662           0 :                         return gnutls_assert_val(ret);
    1663             :                 }
    1664             : 
    1665             :                 return 1;
    1666           4 :         case RECV_STATE_REHANDSHAKE:
    1667           4 :                 session->internals.recv_state = RECV_STATE_0;
    1668             : 
    1669           4 :                 ret = gnutls_handshake(session);
    1670           4 :                 if (ret < 0) {
    1671             :                         /* a temp or fatal error, make sure we reset the state
    1672             :                          * so we can resume on temp errors */
    1673           2 :                         session->internals.recv_state = RECV_STATE_REHANDSHAKE;
    1674           2 :                         return gnutls_assert_val(ret);
    1675             :                 }
    1676             : 
    1677             :                 return 1;
    1678           0 :         case RECV_STATE_ASYNC_HANDSHAKE:
    1679           0 :                 ret = _gnutls_recv_in_buffers(session, GNUTLS_HANDSHAKE, -1, ms);
    1680           0 :                 if (ret < 0 && ret != GNUTLS_E_SESSION_EOF)
    1681           0 :                         return gnutls_assert_val(ret);
    1682             : 
    1683           0 :                 ret = _gnutls13_recv_async_handshake(session);
    1684           0 :                 if (ret < 0)
    1685           0 :                         return gnutls_assert_val(ret);
    1686             : 
    1687             :                 return GNUTLS_E_AGAIN;
    1688             :         case RECV_STATE_EARLY_START_HANDLING:
    1689             :         case RECV_STATE_FALSE_START_HANDLING:
    1690             :                 return 1;
    1691          35 :         case RECV_STATE_FALSE_START:
    1692             :                 /* if false start is not complete we always expect for handshake packets
    1693             :                  * prior to anything else. */
    1694          35 :                 if (session->security_parameters.entity != GNUTLS_CLIENT ||
    1695          35 :                     !(session->internals.flags & GNUTLS_ENABLE_FALSE_START))
    1696           0 :                         return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
    1697             : 
    1698             :                 /* Attempt to complete handshake - we only need to receive */
    1699          35 :                 session->internals.recv_state = RECV_STATE_FALSE_START_HANDLING;
    1700          35 :                 ret = gnutls_handshake(session);
    1701          35 :                 if (ret < 0) {
    1702             :                         /* a temp or fatal error, make sure we reset the state
    1703             :                          * so we can resume on temp errors */
    1704           0 :                         session->internals.recv_state = RECV_STATE_FALSE_START;
    1705           0 :                         return gnutls_assert_val(ret);
    1706             :                 }
    1707             : 
    1708          35 :                 session->internals.recv_state = RECV_STATE_0;
    1709          35 :                 return 1;
    1710          12 :         case RECV_STATE_EARLY_START:
    1711             :                 /* if early start is not complete we always expect for handshake packets
    1712             :                  * prior to anything else. */
    1713          12 :                 if (session->security_parameters.entity != GNUTLS_SERVER ||
    1714          12 :                     !(session->internals.flags & GNUTLS_ENABLE_EARLY_START))
    1715           0 :                         return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
    1716             : 
    1717             :                 /* Attempt to complete handshake - we only need to receive */
    1718          12 :                 session->internals.recv_state = RECV_STATE_EARLY_START_HANDLING;
    1719          12 :                 ret = gnutls_handshake(session);
    1720          12 :                 if (ret < 0) {
    1721             :                         /* a temp or fatal error, make sure we reset the state
    1722             :                          * so we can resume on temp errors */
    1723           0 :                         session->internals.recv_state = RECV_STATE_EARLY_START;
    1724           0 :                         return gnutls_assert_val(ret);
    1725             :                 }
    1726             : 
    1727          12 :                 session->internals.recv_state = RECV_STATE_0;
    1728          12 :                 return 1;
    1729             :         case RECV_STATE_DTLS_RETRANSMIT:
    1730           0 :                 ret = _dtls_retransmit(session);
    1731           0 :                 if (ret < 0)
    1732           0 :                         return gnutls_assert_val(ret);
    1733             : 
    1734           0 :                 session->internals.recv_state = RECV_STATE_0;
    1735             : 
    1736     3063740 :                 FALLTHROUGH;
    1737     3063740 :         case RECV_STATE_0:
    1738             : 
    1739     3063740 :                 _dtls_async_timer_check(session);
    1740     3063740 :                 return 1;
    1741             :         default:
    1742           0 :                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
    1743             :         }
    1744             : }
    1745             : 
    1746             : /* This function behaves exactly like read(). The only difference is
    1747             :  * that it accepts the gnutls_session_t and the content_type_t of data to
    1748             :  * receive (if called by the user the Content is Userdata only)
    1749             :  * It is intended to receive data, under the current session.
    1750             :  */
    1751             : ssize_t
    1752     3063800 : _gnutls_recv_int(gnutls_session_t session, content_type_t type,
    1753             :                  uint8_t * data, size_t data_size, void *seq,
    1754             :                  unsigned int ms)
    1755             : {
    1756     3063800 :         int ret;
    1757             : 
    1758     3063800 :         if ((type != GNUTLS_ALERT && type != GNUTLS_HEARTBEAT)
    1759     2953760 :             && (data_size == 0 || data == NULL))
    1760           0 :                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
    1761             : 
    1762     3063800 :         ret = check_session_status(session, ms);
    1763     3063800 :         if (ret <= 0)
    1764          15 :                 return ret;
    1765             : 
    1766             :         /* If we have enough data in the cache do not bother receiving
    1767             :          * a new packet. (in order to flush the cache)
    1768             :          */
    1769     3063790 :         ret = get_data_from_buffers(session, type, data, data_size, seq);
    1770     3063790 :         if (ret != 0)
    1771         141 :                 return ret;
    1772             : 
    1773     3063640 :         ret = _gnutls_recv_in_buffers(session, type, -1, ms);
    1774     3063640 :         if (ret < 0 && ret != GNUTLS_E_SESSION_EOF)
    1775      658533 :                 return gnutls_assert_val(ret);
    1776             : 
    1777     2411540 :         return get_data_from_buffers(session, type, data, data_size, seq);
    1778             : }
    1779             : 
    1780             : /**
    1781             :  * gnutls_packet_get:
    1782             :  * @packet: is a #gnutls_packet_t type.
    1783             :  * @data: will contain the data present in the @packet structure (may be %NULL)
    1784             :  * @sequence: the 8-bytes of the packet sequence number (may be %NULL)
    1785             :  *
    1786             :  * This function returns the data and sequence number associated with
    1787             :  * the received packet.
    1788             :  *
    1789             :  * Since: 3.3.5
    1790             :  **/
    1791             : 
    1792          21 : void gnutls_packet_get(gnutls_packet_t packet, gnutls_datum_t *data, unsigned char *sequence)
    1793             : {
    1794          21 :         if (unlikely(packet == NULL)) {
    1795           0 :                 gnutls_assert();
    1796           0 :                 if (data) {
    1797           0 :                         data->data = NULL;
    1798           0 :                         data->size = 0;
    1799           0 :                         return;
    1800             :                 }
    1801             :         }
    1802             : 
    1803          21 :         assert(packet != NULL);
    1804             : 
    1805          21 :         if (sequence) {
    1806           0 :                 _gnutls_write_uint64(packet->record_sequence, sequence);
    1807             :         }
    1808             : 
    1809          21 :         if (data) {
    1810          21 :                 data->size = packet->msg.size - packet->mark;
    1811          21 :                 data->data = packet->msg.data + packet->mark;
    1812             :         }
    1813             : }
    1814             : 
    1815             : /**
    1816             :  * gnutls_packet_deinit:
    1817             :  * @packet: is a pointer to a #gnutls_packet_st structure.
    1818             :  *
    1819             :  * This function will deinitialize all data associated with
    1820             :  * the received packet.
    1821             :  *
    1822             :  * Since: 3.3.5
    1823             :  **/
    1824          42 : void gnutls_packet_deinit(gnutls_packet_t packet)
    1825             : {
    1826          42 :         gnutls_free(packet);
    1827          42 : }
    1828             : 
    1829             : /**
    1830             :  * gnutls_record_discard_queued:
    1831             :  * @session: is a #gnutls_session_t type.
    1832             :  *
    1833             :  * This function discards all queued to be sent packets in a DTLS session.
    1834             :  * These are the packets queued after an interrupted gnutls_record_send().
    1835             :  *
    1836             :  * This function can only be used with transports where send() is
    1837             :  * an all-or-nothing operation (e.g., UDP). When partial writes are allowed
    1838             :  * this function will cause session errors.
    1839             :  *
    1840             :  * Returns: The number of bytes discarded.
    1841             :  *
    1842             :  * Since: 3.4.0
    1843             :  **/
    1844             : size_t
    1845           2 : gnutls_record_discard_queued(gnutls_session_t session)
    1846             : {
    1847           2 :         size_t ret = session->internals.record_send_buffer.byte_length;
    1848           2 :         _mbuffer_head_clear(&session->internals.record_send_buffer);
    1849           2 :         return ret;
    1850             : }
    1851             : 
    1852             : /**
    1853             :  * gnutls_record_recv_packet:
    1854             :  * @session: is a #gnutls_session_t type.
    1855             :  * @packet: the structure that will hold the packet data
    1856             :  *
    1857             :  * This is a lower-level function than gnutls_record_recv() and allows
    1858             :  * to directly receive the whole decrypted packet. That avoids a
    1859             :  * memory copy, and is intended to be used by applications seeking high
    1860             :  * performance.
    1861             :  *
    1862             :  * The received packet is accessed using gnutls_packet_get() and
    1863             :  * must be deinitialized using gnutls_packet_deinit(). The returned
    1864             :  * packet will be %NULL if the return value is zero (EOF).
    1865             :  *
    1866             :  * Returns: The number of bytes received and zero on EOF (for stream
    1867             :  * connections).  A negative error code is returned in case of an error.
    1868             :  *
    1869             :  * Since: 3.3.5
    1870             :  **/
    1871             : ssize_t
    1872          42 : gnutls_record_recv_packet(gnutls_session_t session,
    1873             :                           gnutls_packet_t *packet)
    1874             : {
    1875          42 :         int ret;
    1876             : 
    1877          42 :         if (packet == NULL)
    1878           0 :                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
    1879             : 
    1880          42 :         ret = check_session_status(session, session->internals.record_timeout_ms);
    1881          42 :         if (ret <= 0)
    1882           0 :                 return ret;
    1883             : 
    1884          42 :         ret = get_packet_from_buffers(session, GNUTLS_APPLICATION_DATA, packet);
    1885          42 :         if (ret != 0)
    1886           0 :                 return ret;
    1887             : 
    1888          42 :         ret = _gnutls_recv_in_buffers(session, GNUTLS_APPLICATION_DATA, -1,
    1889             :                                       session->internals.record_timeout_ms);
    1890          42 :         if (ret < 0 && ret != GNUTLS_E_SESSION_EOF)
    1891           0 :                 return gnutls_assert_val(ret);
    1892             : 
    1893          42 :         return get_packet_from_buffers(session, GNUTLS_APPLICATION_DATA, packet);
    1894             : }
    1895             : 
    1896             : static
    1897           4 : ssize_t append_data_to_corked(gnutls_session_t session, const void *data, size_t data_size)
    1898             : {
    1899           4 :         int ret;
    1900             : 
    1901           4 :         if (IS_DTLS(session)) {
    1902           6 :                 if (data_size + session->internals.record_presend_buffer.length >
    1903           3 :                         gnutls_dtls_get_data_mtu(session)) {
    1904           1 :                         return gnutls_assert_val(GNUTLS_E_LARGE_PACKET);
    1905             :                 }
    1906             :         }
    1907             : 
    1908           3 :         ret =
    1909           3 :             _gnutls_buffer_append_data(&session->internals.
    1910             :                                        record_presend_buffer, data,
    1911             :                                        data_size);
    1912           3 :         if (ret < 0)
    1913           0 :                 return gnutls_assert_val(ret);
    1914             : 
    1915           3 :         return data_size;
    1916             : }
    1917             : 
    1918             : /**
    1919             :  * gnutls_record_send:
    1920             :  * @session: is a #gnutls_session_t type.
    1921             :  * @data: contains the data to send
    1922             :  * @data_size: is the length of the data
    1923             :  *
    1924             :  * This function has the similar semantics with send().  The only
    1925             :  * difference is that it accepts a GnuTLS session, and uses different
    1926             :  * error codes.
    1927             :  * Note that if the send buffer is full, send() will block this
    1928             :  * function.  See the send() documentation for more information.
    1929             :  *
    1930             :  * You can replace the default push function which is send(), by using
    1931             :  * gnutls_transport_set_push_function().
    1932             :  *
    1933             :  * If the EINTR is returned by the internal push function
    1934             :  * then %GNUTLS_E_INTERRUPTED will be returned. If
    1935             :  * %GNUTLS_E_INTERRUPTED or %GNUTLS_E_AGAIN is returned, you must
    1936             :  * call this function again with the exact same parameters, or provide a
    1937             :  * %NULL pointer for @data and 0 for @data_size, in order to write the
    1938             :  * same data as before. If you wish to discard the previous data instead
    1939             :  * of retrying, you must call gnutls_record_discard_queued() before
    1940             :  * calling this function with different parameters. Note that the latter
    1941             :  * works only on special transports (e.g., UDP).
    1942             :  * cf. gnutls_record_get_direction().
    1943             :  *
    1944             :  * Note that in DTLS this function will return the %GNUTLS_E_LARGE_PACKET
    1945             :  * error code if the send data exceed the data MTU value - as returned
    1946             :  * by gnutls_dtls_get_data_mtu(). The errno value EMSGSIZE
    1947             :  * also maps to %GNUTLS_E_LARGE_PACKET.
    1948             :  * Note that since 3.2.13 this function can be called under cork in DTLS
    1949             :  * mode, and will refuse to send data over the MTU size by returning
    1950             :  * %GNUTLS_E_LARGE_PACKET.
    1951             :  *
    1952             :  * Returns: The number of bytes sent, or a negative error code.  The
    1953             :  *   number of bytes sent might be less than @data_size.  The maximum
    1954             :  *   number of bytes this function can send in a single call depends
    1955             :  *   on the negotiated maximum record size.
    1956             :  **/
    1957             : ssize_t
    1958     2398120 : gnutls_record_send(gnutls_session_t session, const void *data,
    1959             :                    size_t data_size)
    1960             : {
    1961     2398120 :         return gnutls_record_send2(session, data, data_size, 0, 0);
    1962             : }
    1963             : 
    1964             : /**
    1965             :  * gnutls_record_send2:
    1966             :  * @session: is a #gnutls_session_t type.
    1967             :  * @data: contains the data to send
    1968             :  * @data_size: is the length of the data
    1969             :  * @pad: padding to be added to the record
    1970             :  * @flags: must be zero
    1971             :  *
    1972             :  * This function is identical to gnutls_record_send() except that it
    1973             :  * takes an extra argument to specify padding to be added the record.
    1974             :  * To determine the maximum size of padding, use
    1975             :  * gnutls_record_get_max_size() and gnutls_record_overhead_size().
    1976             :  *
    1977             :  * Note that in order for GnuTLS to provide constant time processing
    1978             :  * of padding and data in TLS1.3, the flag %GNUTLS_SAFE_PADDING_CHECK
    1979             :  * must be used in gnutls_init().
    1980             :  *
    1981             :  * Returns: The number of bytes sent, or a negative error code.  The
    1982             :  *   number of bytes sent might be less than @data_size.  The maximum
    1983             :  *   number of bytes this function can send in a single call depends
    1984             :  *   on the negotiated maximum record size.
    1985             :  *
    1986             :  * Since: 3.6.3
    1987             :  **/
    1988             : ssize_t
    1989     2398120 : gnutls_record_send2(gnutls_session_t session, const void *data,
    1990             :                     size_t data_size, size_t pad, unsigned flags)
    1991             : {
    1992     2398120 :         const version_entry_st *vers = get_version(session);
    1993     2398120 :         size_t max_pad = 0;
    1994     2398120 :         int ret;
    1995             : 
    1996     2398120 :         if (unlikely(!session->internals.initial_negotiation_completed)) {
    1997             :                 /* this is to protect buggy applications from sending unencrypted
    1998             :                  * data. We allow sending however, if we are in false or early start
    1999             :                  * handshake state. */
    2000         822 :                 gnutls_mutex_lock(&session->internals.post_negotiation_lock);
    2001             : 
    2002             :                 /* we intentionally re-check the initial_negotation_completed variable
    2003             :                  * to avoid locking during normal operation of gnutls_record_send2() */
    2004         822 :                 if (!session->internals.initial_negotiation_completed &&
    2005         822 :                     session->internals.recv_state != RECV_STATE_FALSE_START &&
    2006         169 :                     session->internals.recv_state != RECV_STATE_FALSE_START_HANDLING &&
    2007          36 :                     session->internals.recv_state != RECV_STATE_EARLY_START &&
    2008          36 :                     session->internals.recv_state != RECV_STATE_EARLY_START_HANDLING &&
    2009          36 :                     !(session->internals.hsk_flags & HSK_EARLY_DATA_IN_FLIGHT)) {
    2010             : 
    2011          33 :                         gnutls_mutex_unlock(&session->internals.post_negotiation_lock);
    2012          33 :                         return gnutls_assert_val(GNUTLS_E_UNAVAILABLE_DURING_HANDSHAKE);
    2013             :                 }
    2014         789 :                 gnutls_mutex_unlock(&session->internals.post_negotiation_lock);
    2015             :         }
    2016             : 
    2017     2398090 :         if (unlikely(!vers))
    2018           0 :                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
    2019             : 
    2020     2398090 :         if (vers->tls13_sem)
    2021      420227 :                 max_pad = gnutls_record_get_max_size(session) - gnutls_record_overhead_size(session);
    2022             : 
    2023     2398090 :         if (pad > max_pad)
    2024           0 :                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
    2025             : 
    2026     2398090 :         switch(session->internals.rsend_state) {
    2027     2398070 :                 case RECORD_SEND_NORMAL:
    2028     2398070 :                         return _gnutls_send_tlen_int(session, GNUTLS_APPLICATION_DATA,
    2029             :                                                      -1, EPOCH_WRITE_CURRENT, data,
    2030             :                                                      data_size, pad, MBUFFER_FLUSH);
    2031           4 :                 case RECORD_SEND_CORKED:
    2032             :                 case RECORD_SEND_CORKED_TO_KU:
    2033           4 :                         return append_data_to_corked(session, data, data_size);
    2034          15 :                 case RECORD_SEND_KEY_UPDATE_1:
    2035          15 :                         _gnutls_buffer_reset(&session->internals.record_key_update_buffer);
    2036             : 
    2037          15 :                         ret = _gnutls_buffer_append_data(&session->internals.record_key_update_buffer,
    2038             :                                                          data, data_size);
    2039          15 :                         if (ret < 0)
    2040           0 :                                 return gnutls_assert_val(ret);
    2041             : 
    2042          15 :                         session->internals.rsend_state = RECORD_SEND_KEY_UPDATE_2;
    2043          15 :                         FALLTHROUGH;
    2044          15 :                 case RECORD_SEND_KEY_UPDATE_2:
    2045          15 :                         ret = gnutls_session_key_update(session, 0);
    2046          15 :                         if (ret < 0)
    2047           0 :                                 return gnutls_assert_val(ret);
    2048             : 
    2049          15 :                         session->internals.rsend_state = RECORD_SEND_KEY_UPDATE_3;
    2050          15 :                         FALLTHROUGH;
    2051          15 :                 case RECORD_SEND_KEY_UPDATE_3:
    2052          30 :                         ret = _gnutls_send_int(session, GNUTLS_APPLICATION_DATA,
    2053             :                                                 -1, EPOCH_WRITE_CURRENT,
    2054          15 :                                                 session->internals.record_key_update_buffer.data,
    2055             :                                                 session->internals.record_key_update_buffer.length,
    2056             :                                                 MBUFFER_FLUSH);
    2057          15 :                         _gnutls_buffer_clear(&session->internals.record_key_update_buffer);
    2058          15 :                         session->internals.rsend_state = RECORD_SEND_NORMAL;
    2059          15 :                         if (ret < 0)
    2060           1 :                                 gnutls_assert();
    2061             : 
    2062          15 :                         return ret;
    2063             :                 default:
    2064           0 :                         return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
    2065             :         }
    2066             : }
    2067             : 
    2068             : /**
    2069             :  * gnutls_record_send_early_data:
    2070             :  * @session: is a #gnutls_session_t type.
    2071             :  * @data: contains the data to send
    2072             :  * @data_size: is the length of the data
    2073             :  *
    2074             :  * This function can be used by a client to send data early in the
    2075             :  * handshake processes when resuming a session.  This is used to
    2076             :  * implement a zero-roundtrip (0-RTT) mode.  It has the same semantics
    2077             :  * as gnutls_record_send().
    2078             :  *
    2079             :  * There may be a limit to the amount of data sent as early data.  Use
    2080             :  * gnutls_record_get_max_early_data_size() to check the limit.  If the
    2081             :  * limit exceeds, this function returns
    2082             :  * %GNUTLS_E_RECORD_LIMIT_REACHED.
    2083             :  *
    2084             :  * Returns: The number of bytes sent, or a negative error code.  The
    2085             :  *   number of bytes sent might be less than @data_size.  The maximum
    2086             :  *   number of bytes this function can send in a single call depends
    2087             :  *   on the negotiated maximum record size.
    2088             :  *
    2089             :  * Since: 3.6.5
    2090             :  **/
    2091           3 : ssize_t gnutls_record_send_early_data(gnutls_session_t session,
    2092             :                                       const void *data,
    2093             :                                       size_t data_size)
    2094             : {
    2095           3 :         int ret;
    2096             : 
    2097           3 :         if (session->security_parameters.entity != GNUTLS_CLIENT)
    2098           0 :                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
    2099             : 
    2100           3 :         if (xsum(session->internals.
    2101             :                  early_data_presend_buffer.length,
    2102             :                  data_size) >
    2103           3 :             session->security_parameters.max_early_data_size)
    2104           0 :                 return gnutls_assert_val(GNUTLS_E_RECORD_LIMIT_REACHED);
    2105             : 
    2106           3 :         ret =
    2107           3 :             _gnutls_buffer_append_data(&session->internals.
    2108             :                                        early_data_presend_buffer, data,
    2109             :                                        data_size);
    2110           3 :         if (ret < 0)
    2111           0 :                 return gnutls_assert_val(ret);
    2112             : 
    2113           3 :         return ret;
    2114             : }
    2115             : 
    2116             : /**
    2117             :  * gnutls_record_recv_early_data:
    2118             :  * @session: is a #gnutls_session_t type.
    2119             :  * @data: the buffer that the data will be read into
    2120             :  * @data_size: the number of requested bytes
    2121             :  *
    2122             :  * This function can be used by a searver to retrieve data sent early
    2123             :  * in the handshake processes when resuming a session.  This is used
    2124             :  * to implement a zero-roundtrip (0-RTT) mode.  It has the same
    2125             :  * semantics as gnutls_record_recv().
    2126             :  *
    2127             :  * This function can be called either in a handshake hook, or after
    2128             :  * the handshake is complete.
    2129             :  *
    2130             :  * Returns: The number of bytes received and zero when early data
    2131             :  * reading is complete.  A negative error code is returned in case of
    2132             :  * an error.  If no early data is received during the handshake, this
    2133             :  * function returns %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE.  The
    2134             :  * number of bytes received might be less than the requested
    2135             :  * @data_size.
    2136             :  *
    2137             :  * Since: 3.6.5
    2138             :  **/
    2139             : ssize_t
    2140           7 : gnutls_record_recv_early_data(gnutls_session_t session, void *data, size_t data_size)
    2141             : {
    2142           7 :         mbuffer_st *bufel;
    2143           7 :         gnutls_datum_t msg;
    2144           7 :         size_t length;
    2145             : 
    2146           7 :         if (session->security_parameters.entity != GNUTLS_SERVER)
    2147           0 :                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
    2148             : 
    2149           7 :         bufel = _mbuffer_head_get_first(&session->internals.early_data_recv_buffer,
    2150             :                                         &msg);
    2151           7 :         if (bufel == NULL)
    2152           3 :                 return
    2153           3 :                     gnutls_assert_val
    2154             :                     (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
    2155             : 
    2156           4 :         length = MIN(msg.size, data_size);
    2157           4 :         memcpy(data, msg.data, length);
    2158           4 :         _mbuffer_head_remove_bytes(&session->internals.early_data_recv_buffer,
    2159             :                                    length);
    2160             : 
    2161           4 :         return length;
    2162             : }
    2163             : 
    2164             : /**
    2165             :  * gnutls_record_cork:
    2166             :  * @session: is a #gnutls_session_t type.
    2167             :  *
    2168             :  * If called, gnutls_record_send() will no longer send any records.
    2169             :  * Any sent records will be cached until gnutls_record_uncork() is called.
    2170             :  *
    2171             :  * This function is safe to use with DTLS after GnuTLS 3.3.0.
    2172             :  *
    2173             :  * Since: 3.1.9
    2174             :  **/
    2175           3 : void gnutls_record_cork(gnutls_session_t session)
    2176             : {
    2177           3 :         session->internals.rsend_state = RECORD_SEND_CORKED;
    2178           3 : }
    2179             : 
    2180             : /**
    2181             :  * gnutls_record_uncork:
    2182             :  * @session: is a #gnutls_session_t type.
    2183             :  * @flags: Could be zero or %GNUTLS_RECORD_WAIT
    2184             :  *
    2185             :  * This resets the effect of gnutls_record_cork(), and flushes any pending
    2186             :  * data. If the %GNUTLS_RECORD_WAIT flag is specified then this
    2187             :  * function will block until the data is sent or a fatal error
    2188             :  * occurs (i.e., the function will retry on %GNUTLS_E_AGAIN and
    2189             :  * %GNUTLS_E_INTERRUPTED).
    2190             :  *
    2191             :  * If the flag %GNUTLS_RECORD_WAIT is not specified and the function
    2192             :  * is interrupted then the %GNUTLS_E_AGAIN or %GNUTLS_E_INTERRUPTED
    2193             :  * errors will be returned. To obtain the data left in the corked
    2194             :  * buffer use gnutls_record_check_corked().
    2195             :  *
    2196             :  * Returns: On success the number of transmitted data is returned, or
    2197             :  * otherwise a negative error code.
    2198             :  *
    2199             :  * Since: 3.1.9
    2200             :  **/
    2201           3 : int gnutls_record_uncork(gnutls_session_t session, unsigned int flags)
    2202             : {
    2203           3 :         int ret;
    2204           3 :         ssize_t total = 0;
    2205           3 :         record_send_state_t orig_state = session->internals.rsend_state;
    2206             : 
    2207           3 :         if (orig_state == RECORD_SEND_CORKED)
    2208           2 :                 session->internals.rsend_state = RECORD_SEND_NORMAL;
    2209           1 :         else if (orig_state == RECORD_SEND_CORKED_TO_KU)
    2210           1 :                 session->internals.rsend_state = RECORD_SEND_KEY_UPDATE_1;
    2211             :         else
    2212             :                 return 0;       /* nothing to be done */
    2213             : 
    2214           6 :         while (session->internals.record_presend_buffer.length > 0) {
    2215           3 :                 if (flags == GNUTLS_RECORD_WAIT) {
    2216           2 :                         do {
    2217           4 :                                 ret =
    2218           2 :                                     gnutls_record_send(session,
    2219             :                                                        session->internals.
    2220           2 :                                                        record_presend_buffer.
    2221             :                                                        data,
    2222             :                                                        session->internals.
    2223             :                                                        record_presend_buffer.
    2224             :                                                        length);
    2225             :                         }
    2226           2 :                         while (ret < 0 && (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED));
    2227             :                 } else {
    2228           1 :                         ret =
    2229           1 :                             gnutls_record_send(session,
    2230             :                                                session->internals.
    2231           1 :                                                record_presend_buffer.data,
    2232             :                                                session->internals.
    2233             :                                                record_presend_buffer.
    2234             :                                                length);
    2235             :                 }
    2236           3 :                 if (ret < 0)
    2237           0 :                         goto fail;
    2238             : 
    2239           3 :                 session->internals.record_presend_buffer.data += ret;
    2240           3 :                 session->internals.record_presend_buffer.length -= ret;
    2241           3 :                 total += ret;
    2242             :         }
    2243             : 
    2244           3 :         return total;
    2245             : 
    2246           0 :       fail:
    2247           0 :         session->internals.rsend_state = orig_state;
    2248           0 :         return ret;
    2249             : }
    2250             : 
    2251             : /**
    2252             :  * gnutls_record_recv:
    2253             :  * @session: is a #gnutls_session_t type.
    2254             :  * @data: the buffer that the data will be read into
    2255             :  * @data_size: the number of requested bytes
    2256             :  *
    2257             :  * This function has the similar semantics with recv().  The only
    2258             :  * difference is that it accepts a GnuTLS session, and uses different
    2259             :  * error codes.
    2260             :  * In the special case that the peer requests a renegotiation, the
    2261             :  * caller will receive an error code of %GNUTLS_E_REHANDSHAKE.  In case
    2262             :  * of a client, this message may be simply ignored, replied with an alert
    2263             :  * %GNUTLS_A_NO_RENEGOTIATION, or replied with a new handshake,
    2264             :  * depending on the client's will. A server receiving this error code
    2265             :  * can only initiate a new handshake or terminate the session.
    2266             :  *
    2267             :  * If %EINTR is returned by the internal pull function (the default
    2268             :  * is recv()) then %GNUTLS_E_INTERRUPTED will be returned.  If
    2269             :  * %GNUTLS_E_INTERRUPTED or %GNUTLS_E_AGAIN is returned, you must
    2270             :  * call this function again to get the data.  See also
    2271             :  * gnutls_record_get_direction().
    2272             :  *
    2273             :  * Returns: The number of bytes received and zero on EOF (for stream
    2274             :  * connections).  A negative error code is returned in case of an error.
    2275             :  * The number of bytes received might be less than the requested @data_size.
    2276             :  **/
    2277             : ssize_t
    2278     2410400 : gnutls_record_recv(gnutls_session_t session, void *data, size_t data_size)
    2279             : {
    2280     2410400 :         if (unlikely(!session->internals.initial_negotiation_completed)) {
    2281             :                 /* this is to protect buggy applications from sending unencrypted
    2282             :                  * data. We allow sending however, if we are in false start handshake
    2283             :                  * state. */
    2284          72 :                 if (session->internals.recv_state != RECV_STATE_FALSE_START &&
    2285             :                     session->internals.recv_state != RECV_STATE_EARLY_START)
    2286          33 :                         return gnutls_assert_val(GNUTLS_E_UNAVAILABLE_DURING_HANDSHAKE);
    2287             :         }
    2288             : 
    2289     2410360 :         return _gnutls_recv_int(session, GNUTLS_APPLICATION_DATA,
    2290             :                                 data, data_size, NULL,
    2291             :                                 session->internals.record_timeout_ms);
    2292             : }
    2293             : 
    2294             : /**
    2295             :  * gnutls_record_recv_seq:
    2296             :  * @session: is a #gnutls_session_t type.
    2297             :  * @data: the buffer that the data will be read into
    2298             :  * @data_size: the number of requested bytes
    2299             :  * @seq: is the packet's 64-bit sequence number. Should have space for 8 bytes.
    2300             :  *
    2301             :  * This function is the same as gnutls_record_recv(), except that
    2302             :  * it returns in addition to data, the sequence number of the data.
    2303             :  * This is useful in DTLS where record packets might be received
    2304             :  * out-of-order. The returned 8-byte sequence number is an
    2305             :  * integer in big-endian format and should be
    2306             :  * treated as a unique message identification.
    2307             :  *
    2308             :  * Returns: The number of bytes received and zero on EOF.  A negative
    2309             :  *   error code is returned in case of an error.  The number of bytes
    2310             :  *   received might be less than @data_size.
    2311             :  *
    2312             :  * Since: 3.0
    2313             :  **/
    2314             : ssize_t
    2315        1274 : gnutls_record_recv_seq(gnutls_session_t session, void *data,
    2316             :                        size_t data_size, unsigned char *seq)
    2317             : {
    2318        1274 :         return _gnutls_recv_int(session, GNUTLS_APPLICATION_DATA,
    2319             :                                 data, data_size, seq,
    2320             :                                 session->internals.record_timeout_ms);
    2321             : }
    2322             : 
    2323             : /**
    2324             :  * gnutls_record_set_timeout:
    2325             :  * @session: is a #gnutls_session_t type.
    2326             :  * @ms: is a timeout value in milliseconds
    2327             :  *
    2328             :  * This function sets the receive timeout for the record layer
    2329             :  * to the provided value. Use an @ms value of zero to disable
    2330             :  * timeout (the default), or %GNUTLS_INDEFINITE_TIMEOUT, to
    2331             :  * set an indefinite timeout.
    2332             :  *
    2333             :  * This function requires to set a pull timeout callback. See
    2334             :  * gnutls_transport_set_pull_timeout_function().
    2335             :  *
    2336             :  * Since: 3.1.7
    2337             :  **/
    2338        5162 : void gnutls_record_set_timeout(gnutls_session_t session, unsigned int ms)
    2339             : {
    2340        5162 :         session->internals.record_timeout_ms = ms;
    2341        5162 : }

Generated by: LCOV version 1.14