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.7 Code Coverage Lines: 63 82 76.8 %
Date: 2019-04-24 03:13:53 Functions: 4 4 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 28 75 37.3 %

           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_PER_SEC 1
      32                 :            : 
      33                 :         54 : static int update_keys(gnutls_session_t session, hs_stage_t stage)
      34                 :            : {
      35                 :         54 :         int ret;
      36                 :            : 
      37                 :        162 :         ret = _tls13_update_secret(session, session->key.proto.tls13.temp_secret,
      38                 :         54 :                                    session->key.proto.tls13.temp_secret_size);
      39         [ -  + ]:         54 :         if (ret < 0)
      40         [ #  # ]:          0 :                 return gnutls_assert_val(ret);
      41                 :            : 
      42                 :         54 :         _gnutls_epoch_bump(session);
      43                 :         54 :         ret = _gnutls_epoch_dup(session, EPOCH_READ_CURRENT);
      44         [ -  + ]:         54 :         if (ret < 0)
      45         [ #  # ]:          0 :                 return gnutls_assert_val(ret);
      46                 :            : 
      47                 :            :         /* If we send a key update during early start, only update our
      48                 :            :          * write keys */
      49         [ -  + ]:         54 :         if (session->internals.recv_state == RECV_STATE_EARLY_START) {
      50                 :          0 :                 ret = _tls13_write_connection_state_init(session, stage);
      51                 :            :         } else {
      52                 :         54 :                 ret = _tls13_connection_state_init(session, stage);
      53                 :            :         }
      54         [ -  + ]:         54 :         if (ret < 0)
      55         [ #  # ]:          0 :                 return gnutls_assert_val(ret);
      56                 :            : 
      57                 :            :         return 0;
      58                 :            : }
      59                 :            : 
      60                 :         25 : int _gnutls13_recv_key_update(gnutls_session_t session, gnutls_buffer_st *buf)
      61                 :            : {
      62                 :         25 :         int ret;
      63                 :         25 :         time_t now = gnutls_time(0);
      64                 :            : 
      65         [ -  + ]:         25 :         if (buf->length != 1)
      66         [ #  # ]:          0 :                 return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
      67                 :            : 
      68         [ -  + ]:         25 :         if (unlikely(now - session->internals.last_key_update < KEY_UPDATES_PER_SEC)) {
      69         [ #  # ]:          0 :                 _gnutls_debug_log("reached maximum number of key updates per second (%d)\n",
      70                 :            :                                   KEY_UPDATES_PER_SEC);
      71         [ #  # ]:          0 :                 return gnutls_assert_val(GNUTLS_E_TOO_MANY_HANDSHAKE_PACKETS);
      72                 :            :         }
      73                 :            : 
      74                 :         25 :         session->internals.last_key_update = now;
      75                 :            : 
      76                 :         25 :         _gnutls_epoch_gc(session);
      77                 :            : 
      78         [ -  + ]:         25 :         _gnutls_handshake_log("HSK[%p]: received TLS 1.3 key update (%u)\n",
      79                 :            :                               session, (unsigned)buf->data[0]);
      80                 :            : 
      81      [ +  +  - ]:         25 :         switch(buf->data[0]) {
      82                 :         14 :         case 0:
      83                 :            :                 /* peer updated its key, not requested our key update */
      84                 :         14 :                 ret = update_keys(session, STAGE_UPD_PEERS);
      85         [ -  + ]:         14 :                 if (ret < 0)
      86         [ #  # ]:          0 :                         return gnutls_assert_val(ret);
      87                 :            : 
      88                 :            :                 break;
      89                 :         11 :         case 1:
      90         [ -  + ]:         11 :                 if (session->internals.hsk_flags & HSK_KEY_UPDATE_ASKED) {
      91                 :            :                         /* if we had asked a key update we shouldn't get this
      92                 :            :                          * reply */
      93         [ #  # ]:          0 :                         return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
      94                 :            :                 }
      95                 :            : 
      96                 :            :                 /* peer updated its key, requested our key update */
      97                 :         11 :                 ret = update_keys(session, STAGE_UPD_PEERS);
      98         [ -  + ]:         11 :                 if (ret < 0)
      99         [ #  # ]:          0 :                         return gnutls_assert_val(ret);
     100                 :            : 
     101                 :            :                 /* we mark that a key update is schedule, and it
     102                 :            :                  * will be performed prior to sending the next application
     103                 :            :                  * message.
     104                 :            :                  */
     105         [ +  + ]:         11 :                 if (session->internals.rsend_state == RECORD_SEND_NORMAL)
     106                 :         10 :                         session->internals.rsend_state = RECORD_SEND_KEY_UPDATE_1;
     107         [ +  - ]:          1 :                 else if (session->internals.rsend_state == RECORD_SEND_CORKED)
     108                 :          1 :                         session->internals.rsend_state = RECORD_SEND_CORKED_TO_KU;
     109                 :            :                 else
     110         [ #  # ]:          0 :                         return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
     111                 :            : 
     112                 :            :                 break;
     113                 :            :         default:
     114         [ #  # ]:          0 :                 return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
     115                 :            :         }
     116                 :            : 
     117                 :         25 :         session->internals.hsk_flags &= ~(unsigned)(HSK_KEY_UPDATE_ASKED);
     118                 :            : 
     119                 :         25 :         return 0;
     120                 :            : }
     121                 :            : 
     122                 :   55532317 : int _gnutls13_send_key_update(gnutls_session_t session, unsigned again, unsigned flags /* GNUTLS_KU_* */)
     123                 :            : {
     124                 :   55532317 :         int ret;
     125                 :   55532317 :         mbuffer_st *bufel = NULL;
     126                 :   55532317 :         uint8_t val;
     127                 :            : 
     128         [ +  + ]:   55532317 :         if (again == 0) {
     129         [ +  + ]:         29 :                 if (flags & GNUTLS_KU_PEER) {
     130                 :            :                         /* mark that we asked a key update to prevent an
     131                 :            :                          * infinite ping pong when receiving the reply */
     132                 :         13 :                         session->internals.hsk_flags |= HSK_KEY_UPDATE_ASKED;
     133                 :         13 :                         val = 0x01;
     134                 :            :                 } else {
     135                 :         16 :                         val = 0x00;
     136                 :            :                 }
     137                 :            : 
     138         [ -  + ]:         29 :                 _gnutls_handshake_log("HSK[%p]: sending key update (%u)\n", session, (unsigned)val);
     139                 :            : 
     140                 :         29 :                 bufel = _gnutls_handshake_alloc(session, 1);
     141         [ -  + ]:         29 :                 if (bufel == NULL)
     142         [ #  # ]:          0 :                         return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
     143                 :            : 
     144                 :         29 :                 _mbuffer_set_udata_size(bufel, 0);
     145                 :         29 :                 ret = _mbuffer_append_data(bufel, &val, 1);
     146         [ -  + ]:         29 :                 if (ret < 0) {
     147         [ #  # ]:          0 :                         gnutls_assert();
     148                 :          0 :                         goto cleanup;
     149                 :            :                 }
     150                 :            : 
     151                 :            :         }
     152                 :            : 
     153                 :   55532317 :         return _gnutls_send_handshake(session, bufel, GNUTLS_HANDSHAKE_KEY_UPDATE);
     154                 :            : 
     155                 :          0 : cleanup:
     156                 :          0 :         _mbuffer_xfree(&bufel);
     157                 :          0 :         return ret;
     158                 :            : }
     159                 :            : 
     160                 :            : /**
     161                 :            :  * gnutls_session_key_update:
     162                 :            :  * @session: is a #gnutls_session_t type.
     163                 :            :  * @flags: zero of %GNUTLS_KU_PEER
     164                 :            :  *
     165                 :            :  * This function will update/refresh the session keys when the
     166                 :            :  * TLS protocol is 1.3 or better. The peer is notified of the
     167                 :            :  * update by sending a message, so this function should be
     168                 :            :  * treated similarly to gnutls_record_send() --i.e., it may
     169                 :            :  * return %GNUTLS_E_AGAIN or %GNUTLS_E_INTERRUPTED.
     170                 :            :  *
     171                 :            :  * When this flag %GNUTLS_KU_PEER is specified, this function
     172                 :            :  * in addition to updating the local keys, will ask the peer to
     173                 :            :  * refresh its keys too.
     174                 :            :  *
     175                 :            :  * If the negotiated version is not TLS 1.3 or better this
     176                 :            :  * function will return %GNUTLS_E_INVALID_REQUEST.
     177                 :            :  *
     178                 :            :  * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
     179                 :            :  *
     180                 :            :  * Since: 3.6.3
     181                 :            :  **/
     182                 :   55532317 : int gnutls_session_key_update(gnutls_session_t session, unsigned flags)
     183                 :            : {
     184                 :   55532317 :         int ret;
     185         [ +  - ]:   55532317 :         const version_entry_st *vers = get_version(session);
     186                 :            : 
     187         [ +  - ]:   55532317 :         if (!vers->tls13_sem)
     188                 :            :                 return GNUTLS_E_INVALID_REQUEST;
     189                 :            : 
     190                 :   55532317 :         ret =
     191                 :   55532317 :             _gnutls13_send_key_update(session, AGAIN(STATE150), flags);
     192                 :   55532317 :         STATE = STATE150;
     193                 :            : 
     194         [ +  + ]:   55532317 :         if (ret < 0) {
     195         [ -  + ]:   55532288 :                 gnutls_assert();
     196                 :   55532288 :                 return ret;
     197                 :            :         }
     198                 :         29 :         STATE = STATE0;
     199                 :            : 
     200                 :         29 :         _gnutls_epoch_gc(session);
     201                 :            : 
     202                 :            :         /* it was completely sent, update the keys */
     203                 :         29 :         ret = update_keys(session, STAGE_UPD_OURS);
     204         [ -  + ]:         29 :         if (ret < 0)
     205         [ #  # ]:          0 :                 return gnutls_assert_val(ret);
     206                 :            : 
     207                 :            :         return 0;
     208                 :            : }

Generated by: LCOV version 1.13