Coverage Report

Created: 2023-03-26 08:33

/src/gnutls/lib/tls13/post_handshake.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
/* Functions that relate to the TLS handshake procedure.
24
 */
25
26
#include "gnutls_int.h"
27
#include "errors.h"
28
#include "dh.h"
29
#include "debug.h"
30
#include "algorithms.h"
31
#include "cipher.h"
32
#include "buffers.h"
33
#include "mbuffers.h"
34
#include "kx.h"
35
#include "handshake.h"
36
#include "num.h"
37
#include "hash_int.h"
38
#include "db.h"
39
#include "hello_ext.h"
40
#include "supplemental.h"
41
#include "auth.h"
42
#include "sslv2_compat.h"
43
#include <auth/cert.h>
44
#include "constate.h"
45
#include <record.h>
46
#include <state.h>
47
#include <random.h>
48
#include <dtls.h>
49
#include "tls13/certificate_request.h"
50
#include "tls13/certificate_verify.h"
51
#include "tls13/certificate.h"
52
#include "tls13/finished.h"
53
54
#undef AGAIN
55
0
#define AGAIN(x) ((x)==(REAUTH_STATE))
56
57
/*
58
 * _gnutls13_reauth_client
59
 * This function performs the client side of the post-handshake authentication
60
 */
61
static
62
int _gnutls13_reauth_client(gnutls_session_t session)
63
0
{
64
0
  int ret = 0;
65
0
  size_t tmp;
66
67
0
  if (!session->internals.initial_negotiation_completed)
68
0
    return gnutls_assert_val(GNUTLS_E_UNAVAILABLE_DURING_HANDSHAKE);
69
70
0
  if (!(session->internals.flags & GNUTLS_POST_HANDSHAKE_AUTH))
71
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
72
73
0
  if (session->internals.reauth_buffer.length == 0)
74
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
75
76
0
  switch (REAUTH_STATE) {
77
0
  case REAUTH_STATE0:
78
79
    /* restore handshake transcript */
80
0
    _gnutls_buffer_reset(&session->internals.handshake_hash_buffer);
81
0
    ret =
82
0
        gnutls_buffer_append_data(&session->
83
0
                internals.handshake_hash_buffer,
84
0
                session->
85
0
                internals.post_handshake_hash_buffer.
86
0
                data,
87
0
                session->
88
0
                internals.post_handshake_hash_buffer.length);
89
0
    if (ret < 0)
90
0
      return gnutls_assert_val(ret);
91
92
    /* append the previously received certificate request message, to the
93
     * transcript. */
94
0
    ret =
95
0
        gnutls_buffer_append_data(&session->
96
0
                internals.handshake_hash_buffer,
97
0
                session->internals.
98
0
                reauth_buffer.data,
99
0
                session->internals.
100
0
                reauth_buffer.length);
101
0
    if (ret < 0)
102
0
      return gnutls_assert_val(ret);
103
104
0
    session->internals.handshake_hash_buffer_prev_len =
105
0
        session->internals.handshake_hash_buffer.length;
106
107
    /* skip the reauth buffer handshake message headers */
108
0
    ret =
109
0
        _gnutls_buffer_pop_prefix32(&session->
110
0
            internals.reauth_buffer, &tmp,
111
0
            0);
112
0
    if (ret < 0)
113
0
      return gnutls_assert_val(ret);
114
115
0
    FALLTHROUGH;
116
0
  case REAUTH_STATE1:
117
0
    ret = _gnutls13_recv_certificate_request_int(session,
118
0
                   &session->internals.reauth_buffer);
119
0
    REAUTH_STATE = REAUTH_STATE1;
120
0
    IMED_RET("recv certificate request", ret, 0);
121
0
    FALLTHROUGH;
122
0
  case REAUTH_STATE2:
123
0
    ret = _gnutls13_send_certificate(session, AGAIN(REAUTH_STATE2));
124
0
    REAUTH_STATE = REAUTH_STATE2;
125
0
    IMED_RET("send certificate", ret, 0);
126
0
    FALLTHROUGH;
127
0
  case REAUTH_STATE3:
128
0
    ret =
129
0
        _gnutls13_send_certificate_verify(session,
130
0
                  AGAIN(REAUTH_STATE3));
131
0
    REAUTH_STATE = REAUTH_STATE3;
132
0
    IMED_RET("send certificate verify", ret, 0);
133
0
    FALLTHROUGH;
134
0
  case REAUTH_STATE4:
135
0
    ret = _gnutls13_send_finished(session, AGAIN(REAUTH_STATE4));
136
0
    REAUTH_STATE = REAUTH_STATE4;
137
0
    IMED_RET("send finished", ret, 0);
138
0
    break;
139
0
  default:
140
0
    return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
141
0
  }
142
143
0
  _gnutls_handshake_hash_buffers_clear(session);
144
0
  _gnutls_buffer_reset(&session->internals.reauth_buffer);
145
0
  REAUTH_STATE = REAUTH_STATE0;
146
147
0
  return 0;
148
0
}
149
150
/*
151
 * _gnutls13_reauth_server
152
 * This function does the server stuff of the post-handshake authentication.
153
 */
154
static
155
int _gnutls13_reauth_server(gnutls_session_t session)
156
0
{
157
0
  int ret = 0;
158
159
0
  if (session->security_parameters.post_handshake_auth == 0 ||
160
0
      (!(session->internals.flags & GNUTLS_POST_HANDSHAKE_AUTH)))
161
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
162
163
0
  if (session->internals.send_cert_req == 0) {
164
0
    _gnutls_debug_log
165
0
        ("You need to call gnutls_certificate_server_set_request to enable post handshake auth\n");
166
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
167
0
  }
168
169
0
  switch (REAUTH_STATE) {
170
0
  case REAUTH_STATE0:
171
    /* restore handshake transcript */
172
0
    _gnutls_buffer_reset(&session->internals.handshake_hash_buffer);
173
0
    ret =
174
0
        gnutls_buffer_append_data(&session->
175
0
                internals.handshake_hash_buffer,
176
0
                session->
177
0
                internals.post_handshake_hash_buffer.
178
0
                data,
179
0
                session->
180
0
                internals.post_handshake_hash_buffer.length);
181
0
    if (ret < 0)
182
0
      return gnutls_assert_val(ret);
183
184
0
    session->internals.handshake_hash_buffer_prev_len =
185
0
        session->internals.handshake_hash_buffer.length;
186
187
0
    FALLTHROUGH;
188
0
  case REAUTH_STATE1:
189
0
    ret =
190
0
        _gnutls13_send_certificate_request(session,
191
0
                   AGAIN(REAUTH_STATE1));
192
0
    REAUTH_STATE = REAUTH_STATE1;
193
0
    IMED_RET("send certificate request", ret, 0);
194
0
    FALLTHROUGH;
195
0
  case REAUTH_STATE2:
196
    /* here we should tolerate application data */
197
0
    ret = _gnutls13_recv_certificate(session);
198
0
    REAUTH_STATE = REAUTH_STATE2;
199
0
    IMED_RET("recv certificate", ret, 0);
200
0
    FALLTHROUGH;
201
0
  case REAUTH_STATE3:
202
0
    ret = _gnutls13_recv_certificate_verify(session);
203
0
    REAUTH_STATE = REAUTH_STATE3;
204
0
    IMED_RET("recv certificate verify", ret, 0);
205
0
    FALLTHROUGH;
206
0
  case REAUTH_STATE4:
207
0
    ret = _gnutls_run_verify_callback(session, GNUTLS_CLIENT);
208
0
    REAUTH_STATE = REAUTH_STATE4;
209
0
    if (ret < 0)
210
0
      return gnutls_assert_val(ret);
211
0
    FALLTHROUGH;
212
0
  case REAUTH_STATE5:
213
0
    ret = _gnutls13_recv_finished(session);
214
0
    REAUTH_STATE = REAUTH_STATE5;
215
0
    IMED_RET("recv finished", ret, 0);
216
0
    break;
217
0
  default:
218
0
    return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
219
0
  }
220
221
0
  _gnutls_handshake_hash_buffers_clear(session);
222
0
  REAUTH_STATE = REAUTH_STATE0;
223
224
0
  return 0;
225
0
}
226
227
/**
228
 * gnutls_reauth:
229
 * @session: is a #gnutls_session_t type.
230
 * @flags: must be zero
231
 *
232
 * This function performs the post-handshake authentication
233
 * for TLS 1.3. The post-handshake authentication is initiated by the server
234
 * by calling this function. Clients respond when %GNUTLS_E_REAUTH_REQUEST
235
 * has been seen while receiving data.
236
 *
237
 * The non-fatal errors expected by this function are:
238
 * %GNUTLS_E_INTERRUPTED, %GNUTLS_E_AGAIN, as well as
239
 * %GNUTLS_E_GOT_APPLICATION_DATA when called on server side.
240
 *
241
 * The former two interrupt the authentication procedure due to the transport
242
 * layer being interrupted, and the latter because there were pending data prior
243
 * to peer initiating the re-authentication. The server should read/process that
244
 * data as unauthenticated and retry calling gnutls_reauth().
245
 *
246
 * When this function is called under TLS1.2 or earlier or the peer didn't
247
 * advertise post-handshake auth, it always fails with
248
 * %GNUTLS_E_INVALID_REQUEST. The verification of the received peers certificate
249
 * is delegated to the session or credentials verification callbacks. A
250
 * server can check whether post handshake authentication is supported
251
 * by the client by checking the session flags with gnutls_session_get_flags().
252
 *
253
 * Prior to calling this function in server side, the function
254
 * gnutls_certificate_server_set_request() must be called setting expectations
255
 * for the received certificate (request or require). If none are set
256
 * this function will return with %GNUTLS_E_INVALID_REQUEST.
257
 *
258
 * Note that post handshake authentication is available irrespective
259
 * of the initial negotiation type (PSK or certificate). In all cases
260
 * however, certificate credentials must be set to the session prior
261
 * to calling this function.
262
 *
263
 * Returns: %GNUTLS_E_SUCCESS on a successful authentication, otherwise a negative error code.
264
 **/
265
int gnutls_reauth(gnutls_session_t session, unsigned int flags)
266
0
{
267
0
  const version_entry_st *vers = get_version(session);
268
269
0
  if (unlikely(!vers->tls13_sem))
270
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
271
272
0
  if (session->security_parameters.entity == GNUTLS_SERVER)
273
0
    return _gnutls13_reauth_server(session);
274
0
  else
275
0
    return _gnutls13_reauth_client(session);
276
0
}