Coverage Report

Created: 2023-03-26 08:33

/src/gnutls/lib/ext/supported_versions.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2001-2012 Free Software Foundation, Inc.
3
 * Copyright (C) 2017-2018 Red Hat, Inc.
4
 *
5
 * Author: Nikos Mavrogiannopoulos
6
 *
7
 * This file is part of GnuTLS.
8
 *
9
 * The GnuTLS is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU Lesser General Public License
11
 * as published by the Free Software Foundation; either version 2.1 of
12
 * the License, or (at your option) any later version.
13
 *
14
 * This library is distributed in the hope that it will be useful, but
15
 * WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 * Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public License
20
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
21
 *
22
 */
23
24
/* This file contains the code for the Max Record Size TLS extension.
25
 */
26
27
#include "gnutls_int.h"
28
#include "errors.h"
29
#include "num.h"
30
#include <hello_ext.h>
31
#include <ext/supported_versions.h>
32
#include "handshake.h"
33
34
static int supported_versions_recv_params(gnutls_session_t session,
35
            const uint8_t * data,
36
            size_t data_size);
37
static int supported_versions_send_params(gnutls_session_t session,
38
            gnutls_buffer_st * extdata);
39
40
const hello_ext_entry_st ext_mod_supported_versions = {
41
  .name = "Supported Versions",
42
  .tls_id = 43,
43
  .gid = GNUTLS_EXTENSION_SUPPORTED_VERSIONS,
44
  .validity =
45
      GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO |
46
      GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO | GNUTLS_EXT_FLAG_HRR |
47
      GNUTLS_EXT_FLAG_TLS,
48
  .client_parse_point = GNUTLS_EXT_VERSION_NEG, /* force parsing prior to EXT_TLS extensions */
49
  .server_parse_point = GNUTLS_EXT_VERSION_NEG,
50
  .recv_func = supported_versions_recv_params,
51
  .send_func = supported_versions_send_params,
52
  .pack_func = NULL,
53
  .unpack_func = NULL,
54
  .deinit_func = NULL,
55
  .cannot_be_overriden = 1
56
};
57
58
static int
59
supported_versions_recv_params(gnutls_session_t session,
60
             const uint8_t * data, size_t data_size)
61
0
{
62
0
  const version_entry_st *vers;
63
0
  uint8_t major, minor;
64
0
  size_t bytes;
65
0
  int ret;
66
67
0
  if (session->security_parameters.entity == GNUTLS_SERVER) {
68
0
    const version_entry_st *old_vers;
69
0
    const version_entry_st *cli_vers = NULL;
70
71
0
    vers = _gnutls_version_max(session);
72
0
    old_vers = get_version(session);
73
74
    /* do not parse this extension when we haven't TLS1.3
75
     * enabled. That is because we cannot handle earlier protocol
76
     * negotiation (such as SSL3.0) with this */
77
0
    if (vers && !vers->tls13_sem)
78
0
      return 0;
79
80
0
    DECR_LEN(data_size, 1);
81
0
    bytes = data[0];
82
0
    data++;
83
84
0
    if (bytes % 2 == 1)
85
0
      return
86
0
          gnutls_assert_val
87
0
          (GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
88
89
0
    DECR_LEN(data_size, bytes);
90
91
0
    if (data_size != 0)
92
0
      return
93
0
          gnutls_assert_val
94
0
          (GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
95
96
0
    while (bytes > 0) {
97
0
      major = data[0];
98
0
      minor = data[1];
99
0
      data += 2;
100
0
      bytes -= 2;
101
102
0
      _gnutls_handshake_log("EXT[%p]: Found version: %d.%d\n",
103
0
                session, (int)major, (int)minor);
104
105
0
      if (!_gnutls_nversion_is_supported
106
0
          (session, major, minor))
107
0
        continue;
108
109
      /* Prefer the latest possible version
110
       * regardless of the client's precedence.  See
111
       * https://gitlab.com/gnutls/gnutls/issues/837
112
       * for the rationale.
113
       */
114
0
      if (!cli_vers ||
115
0
          major > cli_vers->major ||
116
0
          (major == cli_vers->major &&
117
0
           minor > cli_vers->minor))
118
0
        cli_vers = nversion_to_entry(major, minor);
119
0
    }
120
121
0
    if (!cli_vers)
122
0
      return
123
0
          gnutls_assert_val
124
0
          (GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
125
126
0
    session->security_parameters.pversion = cli_vers;
127
128
0
    _gnutls_handshake_log("EXT[%p]: Negotiated version: %d.%d\n",
129
0
              session,
130
0
              (int)cli_vers->major,
131
0
              (int)cli_vers->minor);
132
133
0
    if (old_vers != cli_vers) {
134
      /* regenerate the random value to set
135
       * downgrade sentinel if necessary
136
       */
137
0
      ret = _gnutls_gen_server_random(session, cli_vers->id);
138
0
      if (ret < 0)
139
0
        return gnutls_assert_val(ret);
140
0
    }
141
142
0
    return 0;
143
0
  } else {   /* client */
144
145
0
    if (!have_creds_for_tls13(session)) {
146
      /* if we don't have certificate or PSK (which work under TLS1.3)
147
       * don't try to negotiate version using the extension. We fallback
148
       * instead to the normal TLS negotiation which has a cap on TLS1.2.
149
       */
150
0
      return 0;
151
0
    }
152
153
0
    DECR_LEN(data_size, 2);
154
155
0
    if (data_size != 0)
156
0
      return
157
0
          gnutls_assert_val
158
0
          (GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
159
160
0
    major = data[0];
161
0
    minor = data[1];
162
163
0
    vers = nversion_to_entry(major, minor);
164
0
    if (!vers)
165
0
      return
166
0
          gnutls_assert_val
167
0
          (GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
168
169
0
    set_adv_version(session, major, minor);
170
171
0
    _gnutls_handshake_log("EXT[%p]: Negotiated version: %d.%d\n",
172
0
              session, (int)major, (int)minor);
173
174
0
    if (!vers->tls13_sem)
175
0
      return
176
0
          gnutls_assert_val
177
0
          (GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
178
179
0
    ret = _gnutls_negotiate_version(session, major, minor, 1);
180
0
    if (ret < 0) {
181
0
      gnutls_assert();
182
0
      return ret;
183
0
    }
184
0
  }
185
186
0
  return 0;
187
0
}
188
189
/* returns data_size or a negative number on failure
190
 */
191
static int
192
supported_versions_send_params(gnutls_session_t session,
193
             gnutls_buffer_st * extdata)
194
0
{
195
0
  uint8_t versions[32];
196
0
  size_t versions_size;
197
0
  const version_entry_st *vers;
198
0
  int ret;
199
200
  /* this function sends the client extension data (dnsname) */
201
0
  if (session->security_parameters.entity == GNUTLS_CLIENT) {
202
0
    vers = _gnutls_version_max(session);
203
204
    /* Do not advertise this extension if we are not doing certificate
205
     * or PSK authentication; i.e., do not try to do TLS1.3 if we have
206
     * credentials which do not fit it. */
207
0
    if (!have_creds_for_tls13(session)) {
208
      /* if we don't have certificate or PSK (which work under TLS1.3)
209
       * don't try to negotiate version using the extension. We fallback
210
       * instead to the normal TLS negotiation which has a cap on TLS1.2.
211
       */
212
0
      return 0;
213
0
    }
214
215
    /* do not advertise this extension when we haven't TLS1.3
216
     * enabled. */
217
0
    if (vers && !vers->tls13_sem)
218
0
      return 0;
219
220
0
    ret =
221
0
        _gnutls_write_supported_versions(session, versions,
222
0
                 sizeof(versions));
223
0
    if (ret <= 0) /* if this function doesn't succeed do not send anything */
224
0
      return 0;
225
226
0
    versions_size = ret;
227
228
0
    ret =
229
0
        _gnutls_buffer_append_data_prefix(extdata, 8, versions,
230
0
                  versions_size);
231
0
    if (ret < 0)
232
0
      return gnutls_assert_val(ret);
233
234
0
    return versions_size + 2;
235
0
  } else {
236
0
    vers = get_version(session);
237
0
    if (unlikely(vers == NULL))
238
0
      return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
239
240
    /* don't use this extension to negotiate versions <= 1.2,
241
     * pretend we don't support it, so that we use a single
242
     * code path to negotiate these protocols. */
243
0
    if (!vers->tls13_sem)
244
0
      return 0;
245
246
0
    ret = _gnutls_buffer_append_data(extdata, &vers->major, 1);
247
0
    if (ret < 0)
248
0
      return gnutls_assert_val(ret);
249
250
0
    ret = _gnutls_buffer_append_data(extdata, &vers->minor, 1);
251
0
    if (ret < 0)
252
0
      return gnutls_assert_val(ret);
253
254
0
    return 2;
255
0
  }
256
257
0
  return 0;
258
0
}