Coverage Report

Created: 2023-03-26 08:33

/src/gnutls/lib/tls13/hello_retry.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 "hello_ext.h"
26
#include "handshake.h"
27
#include "tls13/hello_retry.h"
28
#include "auth/cert.h"
29
#include "mbuffers.h"
30
#include "state.h"
31
32
int _gnutls13_send_hello_retry_request(gnutls_session_t session, unsigned again)
33
0
{
34
0
  int ret;
35
0
  mbuffer_st *bufel = NULL;
36
0
  gnutls_buffer_st buf;
37
0
  const version_entry_st *ver;
38
0
  const uint8_t vbuf[2] = { 0x03, 0x03 };
39
40
0
  if (again == 0) {
41
0
    ver = get_version(session);
42
0
    if (unlikely
43
0
        (ver == NULL || session->security_parameters.cs == NULL))
44
0
      return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
45
46
0
    ret = _gnutls_buffer_init_handshake_mbuffer(&buf);
47
0
    if (ret < 0)
48
0
      return gnutls_assert_val(ret);
49
50
0
    ret = _gnutls_buffer_append_data(&buf, vbuf, 2);
51
0
    if (ret < 0)
52
0
      return gnutls_assert_val(ret);
53
54
0
    ret = _gnutls_buffer_append_data(&buf,
55
0
             HRR_RANDOM,
56
0
             GNUTLS_RANDOM_SIZE);
57
0
    if (ret < 0) {
58
0
      gnutls_assert();
59
0
      goto cleanup;
60
0
    }
61
62
0
    ret = _gnutls_buffer_append_data_prefix(&buf, 8,
63
0
              session->security_parameters.session_id,
64
0
              session->security_parameters.session_id_size);
65
0
    if (ret < 0) {
66
0
      gnutls_assert();
67
0
      goto cleanup;
68
0
    }
69
70
0
    ret =
71
0
        _gnutls_buffer_append_data(&buf,
72
0
                 session->security_parameters.
73
0
                 cs->id, 2);
74
0
    if (ret < 0) {
75
0
      gnutls_assert();
76
0
      goto cleanup;
77
0
    }
78
79
    /* compression */
80
0
    ret = _gnutls_buffer_append_prefix(&buf, 8, 0);
81
0
    if (ret < 0) {
82
0
      gnutls_assert();
83
0
      goto cleanup;
84
0
    }
85
86
0
    ret = _gnutls_gen_hello_extensions(session, &buf,
87
0
               GNUTLS_EXT_FLAG_HRR,
88
0
               GNUTLS_EXT_ANY);
89
0
    if (ret < 0) {
90
0
      gnutls_assert();
91
0
      goto cleanup;
92
0
    }
93
94
    /* reset extensions sent by this session to allow re-sending them */
95
0
    session->internals.used_exts = 0;
96
97
0
    reset_binders(session);
98
99
0
    bufel = _gnutls_buffer_to_mbuffer(&buf);
100
0
  }
101
102
0
  return _gnutls_send_handshake(session, bufel,
103
0
              GNUTLS_HANDSHAKE_HELLO_RETRY_REQUEST);
104
105
0
 cleanup:
106
0
  _gnutls_buffer_clear(&buf);
107
0
  return ret;
108
0
}
109
110
int
111
_gnutls13_recv_hello_retry_request(gnutls_session_t session,
112
           gnutls_buffer_st * buf)
113
0
{
114
0
  int ret;
115
0
  uint8_t tmp[2];
116
0
  const gnutls_cipher_suite_entry_st *cs;
117
0
  const mac_entry_st *prf;
118
0
  gnutls_datum_t session_id;
119
0
  uint8_t random[GNUTLS_RANDOM_SIZE];
120
121
  /* only under TLS 1.3 */
122
0
  if (IS_DTLS(session))
123
0
    return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
124
125
0
  if (session->internals.hsk_flags & HSK_HRR_RECEIVED)
126
0
    return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
127
128
0
  session->internals.hsk_flags |= HSK_HRR_RECEIVED;
129
130
  /* version */
131
0
  ret = _gnutls_buffer_pop_data(buf, tmp, 2);
132
0
  if (ret < 0)
133
0
    return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
134
135
0
  if (unlikely(tmp[0] != 0x03 || tmp[1] != 0x03))
136
0
    return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
137
138
0
  ret = _gnutls_buffer_pop_data(buf, random, GNUTLS_RANDOM_SIZE);
139
0
  if (ret < 0)
140
0
    return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
141
142
0
  if (memcmp(random, HRR_RANDOM, GNUTLS_RANDOM_SIZE) != 0) {
143
0
    return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
144
0
  }
145
146
0
  ret = _gnutls_buffer_pop_datum_prefix8(buf, &session_id);
147
0
  if (ret < 0)
148
0
    return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
149
150
  /* read ciphersuites */
151
0
  ret = _gnutls_buffer_pop_data(buf, tmp, 2);
152
0
  if (ret < 0)
153
0
    return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
154
155
0
  cs = ciphersuite_to_entry(tmp);
156
0
  if (unlikely(cs == NULL))
157
0
    return gnutls_assert_val(GNUTLS_E_UNKNOWN_CIPHER_SUITE);
158
159
0
  _gnutls_handshake_log("EXT[%p]: Hello Retry Request with %s\n", session,
160
0
            cs->name);
161
0
  memcpy(session->internals.hrr_cs, cs->id, 2);
162
163
0
  prf = mac_to_entry(cs->prf);
164
0
  if (unlikely(prf == NULL))
165
0
    return gnutls_assert_val(GNUTLS_E_UNKNOWN_CIPHER_SUITE);
166
167
  /* compression */
168
0
  ret = _gnutls_buffer_pop_data(buf, tmp, 1);
169
0
  if (ret < 0)
170
0
    return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
171
172
0
  if (unlikely(tmp[0] != 0))
173
0
    return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
174
175
0
  ret = _gnutls13_handshake_hash_buffers_synth(session, prf, 1);
176
0
  if (ret < 0)
177
0
    return gnutls_assert_val(ret);
178
179
0
  if (buf->length <= 2) {
180
    /* no extensions present */
181
0
    return gnutls_assert_val(GNUTLS_E_UNEXPECTED_EXTENSIONS_LENGTH);
182
0
  }
183
184
  /* figure version first */
185
0
  ret =
186
0
      _gnutls_parse_hello_extensions(session, GNUTLS_EXT_FLAG_HRR,
187
0
             GNUTLS_EXT_VERSION_NEG,
188
0
             buf->data, buf->length);
189
0
  if (ret < 0)
190
0
    return gnutls_assert_val(ret);
191
192
  /* parse the rest of extensions */
193
0
  ret =
194
0
      _gnutls_parse_hello_extensions(session, GNUTLS_EXT_FLAG_HRR,
195
0
             GNUTLS_EXT_ANY, buf->data,
196
0
             buf->length);
197
0
  if (ret < 0)
198
0
    return gnutls_assert_val(ret);
199
200
0
  session->internals.used_exts = 0;
201
202
0
  return 0;
203
0
}