Coverage Report

Created: 2023-03-26 07:33

/src/gnutls/lib/tls13/finished.c
Line
Count
Source (jump to first uncovered line)
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/finished.h"
27
#include "mem.h"
28
#include "mbuffers.h"
29
#include "secrets.h"
30
31
int _gnutls13_compute_finished(const mac_entry_st * prf,
32
             const uint8_t * base_key,
33
             gnutls_buffer_st * handshake_hash_buffer,
34
             void *out)
35
0
{
36
0
  int ret;
37
0
  uint8_t fkey[MAX_HASH_SIZE];
38
0
  uint8_t ts_hash[MAX_HASH_SIZE];
39
40
0
  ret = _tls13_expand_secret2(prf,
41
0
            "finished", 8,
42
0
            NULL, 0, base_key, prf->output_size, fkey);
43
0
  if (ret < 0)
44
0
    return gnutls_assert_val(ret);
45
46
0
  ret = gnutls_hash_fast(MAC_TO_DIG(prf->id),
47
0
             handshake_hash_buffer->data,
48
0
             handshake_hash_buffer->length, ts_hash);
49
0
  if (ret < 0)
50
0
    return gnutls_assert_val(ret);
51
52
0
  ret = gnutls_hmac_fast(prf->id,
53
0
             fkey, prf->output_size,
54
0
             ts_hash, prf->output_size, out);
55
0
  if (ret < 0)
56
0
    return gnutls_assert_val(ret);
57
58
0
  return 0;
59
0
}
60
61
int _gnutls13_recv_finished(gnutls_session_t session)
62
0
{
63
0
  int ret;
64
0
  gnutls_buffer_st buf;
65
0
  uint8_t verifier[MAX_HASH_SIZE];
66
0
  const uint8_t *base_key;
67
0
  unsigned hash_size;
68
69
0
  if (unlikely(session->security_parameters.prf == NULL))
70
0
    return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
71
72
0
  hash_size = session->security_parameters.prf->output_size;
73
74
0
  if (!session->internals.initial_negotiation_completed) {
75
0
    if (session->security_parameters.entity == GNUTLS_CLIENT)
76
0
      base_key = session->key.proto.tls13.hs_skey;
77
0
    else
78
0
      base_key = session->key.proto.tls13.hs_ckey;
79
0
  } else {
80
0
    if (session->security_parameters.entity == GNUTLS_CLIENT)
81
0
      base_key = session->key.proto.tls13.ap_skey;
82
0
    else
83
0
      base_key = session->key.proto.tls13.ap_ckey;
84
0
  }
85
86
0
  ret = _gnutls13_compute_finished(session->security_parameters.prf,
87
0
           base_key,
88
0
           &session->
89
0
           internals.handshake_hash_buffer,
90
0
           verifier);
91
0
  if (ret < 0) {
92
0
    gnutls_assert();
93
0
    goto cleanup;
94
0
  }
95
96
0
  ret =
97
0
      _gnutls_recv_handshake(session, GNUTLS_HANDSHAKE_FINISHED, 0, &buf);
98
0
  if (ret < 0)
99
0
    return gnutls_assert_val(ret);
100
101
0
  _gnutls_handshake_log("HSK[%p]: parsing finished\n", session);
102
103
0
  if (buf.length != hash_size) {
104
0
    gnutls_assert();
105
0
    ret = GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
106
0
    goto cleanup;
107
0
  }
108
#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
109
# warning This is unsafe for production builds
110
#else
111
0
  if (gnutls_memcmp(verifier, buf.data, buf.length) != 0) {
112
0
    gnutls_assert();
113
0
    ret = GNUTLS_E_ERROR_IN_FINISHED_PACKET;
114
0
    goto cleanup;
115
0
  }
116
0
#endif
117
118
0
  ret = 0;
119
0
 cleanup:
120
121
0
  _gnutls_buffer_clear(&buf);
122
0
  return ret;
123
0
}
124
125
int _gnutls13_send_finished(gnutls_session_t session, unsigned again)
126
0
{
127
0
  int ret;
128
0
  uint8_t verifier[MAX_HASH_SIZE];
129
0
  mbuffer_st *bufel = NULL;
130
0
  const uint8_t *base_key;
131
0
  unsigned hash_size;
132
133
0
  if (again == 0) {
134
0
    if (unlikely(session->security_parameters.prf == NULL))
135
0
      return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
136
137
0
    hash_size = session->security_parameters.prf->output_size;
138
139
0
    if (!session->internals.initial_negotiation_completed) {
140
0
      if (session->security_parameters.entity ==
141
0
          GNUTLS_CLIENT)
142
0
        base_key = session->key.proto.tls13.hs_ckey;
143
0
      else
144
0
        base_key = session->key.proto.tls13.hs_skey;
145
0
    } else {
146
0
      if (session->security_parameters.entity ==
147
0
          GNUTLS_CLIENT)
148
0
        base_key = session->key.proto.tls13.ap_ckey;
149
0
      else
150
0
        base_key = session->key.proto.tls13.ap_skey;
151
0
    }
152
153
0
    ret =
154
0
        _gnutls13_compute_finished(session->security_parameters.prf,
155
0
                 base_key,
156
0
                 &session->
157
0
                 internals.handshake_hash_buffer,
158
0
                 verifier);
159
0
    if (ret < 0) {
160
0
      gnutls_assert();
161
0
      goto cleanup;
162
0
    }
163
164
0
    _gnutls_handshake_log("HSK[%p]: sending finished\n", session);
165
166
0
    bufel = _gnutls_handshake_alloc(session, hash_size);
167
0
    if (bufel == NULL)
168
0
      return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
169
170
0
    _mbuffer_set_udata_size(bufel, 0);
171
0
    ret = _mbuffer_append_data(bufel, verifier, hash_size);
172
0
    if (ret < 0) {
173
0
      gnutls_assert();
174
0
      goto cleanup;
175
0
    }
176
0
  }
177
178
0
  return _gnutls_send_handshake(session, bufel,
179
0
              GNUTLS_HANDSHAKE_FINISHED);
180
181
0
 cleanup:
182
0
  _mbuffer_xfree(&bufel);
183
0
  return ret;
184
0
}