LCOV - code coverage report
Current view: top level - builds/gnutls/coverage/gnutls-git/lib/tls13 - key_update.c (source / functions) Hit Total Coverage
Test: GnuTLS-3.6.8 Code Coverage Lines: 69 85 81.2 %
Date: 2019-07-21 03:10:42 Functions: 4 4 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 36 77 46.8 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (C) 2017 Red Hat, Inc.
       3                 :            :  *
       4                 :            :  * Author: Nikos Mavrogiannopoulos
       5                 :            :  *
       6                 :            :  * This file is part of GnuTLS.
       7                 :            :  *
       8                 :            :  * The GnuTLS is free software; you can redistribute it and/or
       9                 :            :  * modify it under the terms of the GNU Lesser General Public License
      10                 :            :  * as published by the Free Software Foundation; either version 2.1 of
      11                 :            :  * the License, or (at your option) any later version.
      12                 :            :  *
      13                 :            :  * This library is distributed in the hope that it will be useful, but
      14                 :            :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      15                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16                 :            :  * Lesser General Public License for more details.
      17                 :            :  *
      18                 :            :  * You should have received a copy of the GNU Lesser General Public License
      19                 :            :  * along with this program.  If not, see <https://www.gnu.org/licenses/>
      20                 :            :  *
      21                 :            :  */
      22                 :            : 
      23                 :            : #include "gnutls_int.h"
      24                 :            : #include "errors.h"
      25                 :            : #include "handshake.h"
      26                 :            : #include "tls13/key_update.h"
      27                 :            : #include "mem.h"
      28                 :            : #include "mbuffers.h"
      29                 :            : #include "secrets.h"
      30                 :            : 
      31                 :            : #define KEY_UPDATES_WINDOW 1000
      32                 :            : #define KEY_UPDATES_PER_WINDOW 8
      33                 :            : 
      34                 :         95 : static int update_keys(gnutls_session_t session, hs_stage_t stage)
      35                 :            : {
      36                 :         95 :         int ret;
      37                 :            : 
      38                 :        285 :         ret = _tls13_update_secret(session, session->key.proto.tls13.temp_secret,
      39                 :         95 :                                    session->key.proto.tls13.temp_secret_size);
      40         [ -  + ]:         95 :         if (ret < 0)
      41         [ #  # ]:          0 :                 return gnutls_assert_val(ret);
      42                 :            : 
      43                 :         95 :         _gnutls_epoch_bump(session);
      44                 :         95 :         ret = _gnutls_epoch_dup(session, EPOCH_READ_CURRENT);
      45         [ -  + ]:         95 :         if (ret < 0)
      46         [ #  # ]:          0 :                 return gnutls_assert_val(ret);
      47                 :            : 
      48                 :            :         /* If we send a key update during early start, only update our
      49                 :            :          * write keys */
      50         [ -  + ]:         95 :         if (session->internals.recv_state == RECV_STATE_EARLY_START) {
      51                 :          0 :                 ret = _tls13_write_connection_state_init(session, stage);
      52                 :            :         } else {
      53                 :         95 :                 ret = _tls13_connection_state_init(session, stage);
      54                 :            :         }
      55         [ -  + ]:         95 :         if (ret < 0)
      56         [ #  # ]:          0 :                 return gnutls_assert_val(ret);
      57                 :            : 
      58                 :            :         return 0;
      59                 :            : }
      60                 :            : 
      61                 :         46 : int _gnutls13_recv_key_update(gnutls_session_t session, gnutls_buffer_st *buf)
      62                 :            : {
      63                 :         46 :         int ret;
      64                 :         46 :         struct timespec now;
      65                 :            : 
      66         [ -  + ]:         46 :         if (buf->length != 1)
      67         [ #  # ]:          0 :                 return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
      68                 :            : 
      69                 :         46 :         gnutls_gettime(&now);
      70                 :            : 
      71                 :            :         /* Roll over the counter if the time window has elapsed */
      72   [ +  +  +  + ]:         67 :         if (session->internals.key_update_count == 0 ||
      73                 :         21 :             timespec_sub_ms(&now, &session->internals.last_key_update) >
      74                 :            :             KEY_UPDATES_WINDOW) {
      75                 :         31 :                 session->internals.last_key_update = now;
      76                 :         31 :                 session->internals.key_update_count = 0;
      77                 :            :         }
      78                 :            : 
      79         [ +  + ]:         46 :         if (unlikely(++session->internals.key_update_count >
      80                 :            :                      KEY_UPDATES_PER_WINDOW)) {
      81         [ -  + ]:          1 :                 _gnutls_debug_log("reached maximum number of key updates per %d milliseconds (%d)\n",
      82                 :            :                                   KEY_UPDATES_WINDOW,
      83                 :            :                                   KEY_UPDATES_PER_WINDOW);
      84         [ -  + ]:          1 :                 return gnutls_assert_val(GNUTLS_E_TOO_MANY_HANDSHAKE_PACKETS);
      85                 :            :         }
      86                 :            : 
      87                 :         45 :         _gnutls_epoch_gc(session);
      88                 :            : 
      89         [ -  + ]:         45 :         _gnutls_handshake_log("HSK[%p]: received TLS 1.3 key update (%u)\n",
      90                 :            :                               session, (unsigned)buf->data[0]);
      91                 :            : 
      92      [ +  +  - ]:         45 :         switch(buf->data[0]) {
      93                 :         17 :         case 0:
      94                 :            :                 /* peer updated its key, not requested our key update */
      95                 :         17 :                 ret = update_keys(session, STAGE_UPD_PEERS);
      96         [ -  + ]:         17 :                 if (ret < 0)
      97         [ #  # ]:          0 :                         return gnutls_assert_val(ret);
      98                 :            : 
      99                 :            :                 break;
     100                 :         28 :         case 1:
     101         [ -  + ]:         28 :                 if (session->internals.hsk_flags & HSK_KEY_UPDATE_ASKED) {
     102                 :            :                         /* if we had asked a key update we shouldn't get this
     103                 :            :                          * reply */
     104         [ #  # ]:          0 :                         return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
     105                 :            :                 }
     106                 :            : 
     107                 :            :                 /* peer updated its key, requested our key update */
     108                 :         28 :                 ret = update_keys(session, STAGE_UPD_PEERS);
     109         [ -  + ]:         28 :                 if (ret < 0)
     110         [ #  # ]:          0 :                         return gnutls_assert_val(ret);
     111                 :            : 
     112                 :            :                 /* we mark that a key update is schedule, and it
     113                 :            :                  * will be performed prior to sending the next application
     114                 :            :                  * message.
     115                 :            :                  */
     116         [ +  + ]:         28 :                 if (session->internals.rsend_state == RECORD_SEND_NORMAL)
     117                 :         13 :                         session->internals.rsend_state = RECORD_SEND_KEY_UPDATE_1;
     118         [ +  + ]:         15 :                 else if (session->internals.rsend_state == RECORD_SEND_CORKED)
     119                 :          1 :                         session->internals.rsend_state = RECORD_SEND_CORKED_TO_KU;
     120                 :            : 
     121                 :            :                 break;
     122                 :            :         default:
     123         [ #  # ]:          0 :                 return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
     124                 :            :         }
     125                 :            : 
     126                 :         45 :         session->internals.hsk_flags &= ~(unsigned)(HSK_KEY_UPDATE_ASKED);
     127                 :            : 
     128                 :         45 :         return 0;
     129                 :            : }
     130                 :            : 
     131                 :   59336889 : int _gnutls13_send_key_update(gnutls_session_t session, unsigned again, unsigned flags /* GNUTLS_KU_* */)
     132                 :            : {
     133                 :   59336889 :         int ret;
     134                 :   59336889 :         mbuffer_st *bufel = NULL;
     135                 :   59336889 :         uint8_t val;
     136                 :            : 
     137         [ +  + ]:   59336889 :         if (again == 0) {
     138         [ +  + ]:         50 :                 if (flags & GNUTLS_KU_PEER) {
     139                 :            :                         /* mark that we asked a key update to prevent an
     140                 :            :                          * infinite ping pong when receiving the reply */
     141                 :         31 :                         session->internals.hsk_flags |= HSK_KEY_UPDATE_ASKED;
     142                 :         31 :                         val = 0x01;
     143                 :            :                 } else {
     144                 :         19 :                         val = 0x00;
     145                 :            :                 }
     146                 :            : 
     147         [ -  + ]:         50 :                 _gnutls_handshake_log("HSK[%p]: sending key update (%u)\n", session, (unsigned)val);
     148                 :            : 
     149                 :         50 :                 bufel = _gnutls_handshake_alloc(session, 1);
     150         [ -  + ]:         50 :                 if (bufel == NULL)
     151         [ #  # ]:          0 :                         return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
     152                 :            : 
     153                 :         50 :                 _mbuffer_set_udata_size(bufel, 0);
     154                 :         50 :                 ret = _mbuffer_append_data(bufel, &val, 1);
     155         [ -  + ]:         50 :                 if (ret < 0) {
     156         [ #  # ]:          0 :                         gnutls_assert();
     157                 :          0 :                         goto cleanup;
     158                 :            :                 }
     159                 :            : 
     160                 :            :         }
     161                 :            : 
     162                 :   59336889 :         return _gnutls_send_handshake(session, bufel, GNUTLS_HANDSHAKE_KEY_UPDATE);
     163                 :            : 
     164                 :          0 : cleanup:
     165                 :          0 :         _mbuffer_xfree(&bufel);
     166                 :          0 :         return ret;
     167                 :            : }
     168                 :            : 
     169                 :            : /**
     170                 :            :  * gnutls_session_key_update:
     171                 :            :  * @session: is a #gnutls_session_t type.
     172                 :            :  * @flags: zero of %GNUTLS_KU_PEER
     173                 :            :  *
     174                 :            :  * This function will update/refresh the session keys when the
     175                 :            :  * TLS protocol is 1.3 or better. The peer is notified of the
     176                 :            :  * update by sending a message, so this function should be
     177                 :            :  * treated similarly to gnutls_record_send() --i.e., it may
     178                 :            :  * return %GNUTLS_E_AGAIN or %GNUTLS_E_INTERRUPTED.
     179                 :            :  *
     180                 :            :  * When this flag %GNUTLS_KU_PEER is specified, this function
     181                 :            :  * in addition to updating the local keys, will ask the peer to
     182                 :            :  * refresh its keys too.
     183                 :            :  *
     184                 :            :  * If the negotiated version is not TLS 1.3 or better this
     185                 :            :  * function will return %GNUTLS_E_INVALID_REQUEST.
     186                 :            :  *
     187                 :            :  * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
     188                 :            :  *
     189                 :            :  * Since: 3.6.3
     190                 :            :  **/
     191                 :   59336889 : int gnutls_session_key_update(gnutls_session_t session, unsigned flags)
     192                 :            : {
     193                 :   59336889 :         int ret;
     194         [ +  - ]:   59336889 :         const version_entry_st *vers = get_version(session);
     195                 :            : 
     196         [ +  - ]:   59336889 :         if (!vers->tls13_sem)
     197                 :            :                 return GNUTLS_E_INVALID_REQUEST;
     198                 :            : 
     199                 :   59336889 :         ret =
     200                 :   59336889 :             _gnutls13_send_key_update(session, AGAIN(STATE150), flags);
     201                 :   59336889 :         STATE = STATE150;
     202                 :            : 
     203         [ +  + ]:   59336889 :         if (ret < 0) {
     204         [ -  + ]:   59336839 :                 gnutls_assert();
     205                 :   59336839 :                 return ret;
     206                 :            :         }
     207                 :         50 :         STATE = STATE0;
     208                 :            : 
     209                 :         50 :         _gnutls_epoch_gc(session);
     210                 :            : 
     211                 :            :         /* it was completely sent, update the keys */
     212                 :         50 :         ret = update_keys(session, STAGE_UPD_OURS);
     213         [ -  + ]:         50 :         if (ret < 0)
     214         [ #  # ]:          0 :                 return gnutls_assert_val(ret);
     215                 :            : 
     216                 :            :         return 0;
     217                 :            : }

Generated by: LCOV version 1.13