Coverage Report

Created: 2023-03-26 08:33

/src/gnutls/lib/session.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2000-2016 Free Software Foundation, Inc.
3
 * Copyright (C) 2017 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
#include "gnutls_int.h"
24
#include "errors.h"
25
#include "debug.h"
26
#include <session_pack.h>
27
#include <datum.h>
28
#include "buffers.h"
29
#include "state.h"
30
#include "ext/cert_types.h"
31
#include <minmax.h>
32
33
/**
34
 * gnutls_session_get_data:
35
 * @session: is a #gnutls_session_t type.
36
 * @session_data: is a pointer to space to hold the session.
37
 * @session_data_size: is the session_data's size, or it will be set by the function.
38
 *
39
 * Returns all session parameters needed to be stored to support resumption,
40
 * in a pre-allocated buffer.
41
 *
42
 * See gnutls_session_get_data2() for more information.
43
 *
44
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
45
 *   an error code is returned.
46
 **/
47
int
48
gnutls_session_get_data(gnutls_session_t session,
49
      void *session_data, size_t *session_data_size)
50
0
{
51
52
0
  gnutls_datum_t psession;
53
0
  int ret;
54
55
0
  ret = gnutls_session_get_data2(session, &psession);
56
0
  if (ret < 0) {
57
0
    gnutls_assert();
58
0
    return ret;
59
0
  }
60
61
0
  if (psession.size > *session_data_size) {
62
0
    *session_data_size = psession.size;
63
0
    ret = GNUTLS_E_SHORT_MEMORY_BUFFER;
64
0
    goto error;
65
0
  }
66
0
  *session_data_size = psession.size;
67
68
0
  if (session_data != NULL)
69
0
    memcpy(session_data, psession.data, psession.size);
70
71
0
  ret = 0;
72
73
0
 error:
74
0
  _gnutls_free_datum(&psession);
75
0
  return ret;
76
0
}
77
78
0
#define EMPTY_DATA "\x00\x00\x00\x00"
79
0
#define EMPTY_DATA_SIZE 4
80
81
/**
82
 * gnutls_session_get_data2:
83
 * @session: is a #gnutls_session_t type.
84
 * @data: is a pointer to a datum that will hold the session.
85
 *
86
 * Returns necessary parameters to support resumption. The client
87
 * should call this function and store the returned session data. A session
88
 * can be resumed later by calling gnutls_session_set_data() with the returned
89
 * data. Note that under TLS 1.3, it is recommended for clients to use
90
 * session parameters only once, to prevent passive-observers from correlating
91
 * the different connections.
92
 *
93
 * The returned @data are allocated and must be released using gnutls_free().
94
 *
95
 * This function will fail if called prior to handshake completion. In
96
 * case of false start TLS, the handshake completes only after data have
97
 * been successfully received from the peer.
98
 *
99
 * Under TLS1.3 session resumption is possible only after a session ticket
100
 * is received by the client. To ensure that such a ticket has been received use
101
 * gnutls_session_get_flags() and check for flag %GNUTLS_SFLAGS_SESSION_TICKET;
102
 * if this flag is not set, this function will wait for a new ticket within
103
 * an estimated roundtrip, and if not received will return dummy data which
104
 * cannot lead to resumption.
105
 *
106
 * To get notified when new tickets are received by the server
107
 * use gnutls_handshake_set_hook_function() to wait for %GNUTLS_HANDSHAKE_NEW_SESSION_TICKET
108
 * messages. Each call of gnutls_session_get_data2() after a ticket is
109
 * received, will return session resumption data corresponding to the last
110
 * received ticket.
111
 *
112
 * Note that this function under TLS1.3 requires a callback to be set with
113
 * gnutls_transport_set_pull_timeout_function() for successful operation. There
114
 * was a bug before 3.6.10 which could make this function fail if that callback
115
 * was not set. On later versions if not set, the function will return a successful
116
 * error code, but will return dummy data that cannot lead to a resumption.
117
 *
118
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
119
 *   an error code is returned.
120
 **/
121
int gnutls_session_get_data2(gnutls_session_t session, gnutls_datum_t * data)
122
0
{
123
0
  const version_entry_st *vers = get_version(session);
124
0
  int ret;
125
126
0
  if (data == NULL || vers == NULL) {
127
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
128
0
  }
129
130
0
  if (vers->tls13_sem
131
0
      && !(session->internals.hsk_flags & HSK_TICKET_RECEIVED)) {
132
0
    unsigned ertt = session->internals.ertt;
133
    /* use our estimation of round-trip + some time for the server to calculate
134
     * the value(s). */
135
0
    ertt += 60;
136
137
    /* we cannot use a read with timeout if the caller has not set
138
     * a callback with gnutls_transport_set_pull_timeout_function() */
139
0
    if (NO_TIMEOUT_FUNC_SET(session)
140
0
        || (session->internals.flags & GNUTLS_NONBLOCK)) {
141
0
      if (!(session->internals.flags & GNUTLS_NONBLOCK))
142
0
        _gnutls_debug_log
143
0
            ("TLS1.3 works efficiently if a callback with gnutls_transport_set_pull_timeout_function() is set\n");
144
0
    } else {
145
      /* wait for a message with timeout */
146
0
      ret =
147
0
          _gnutls_recv_in_buffers(session,
148
0
                GNUTLS_APPLICATION_DATA, -1,
149
0
                ertt);
150
0
      if (ret < 0 && (gnutls_error_is_fatal(ret)
151
0
          && ret != GNUTLS_E_TIMEDOUT)) {
152
0
        return gnutls_assert_val(ret);
153
0
      }
154
0
    }
155
156
0
    if (!(session->internals.hsk_flags & HSK_TICKET_RECEIVED)) {
157
0
      ret =
158
0
          _gnutls_set_datum(data, EMPTY_DATA,
159
0
                EMPTY_DATA_SIZE);
160
0
      if (ret < 0)
161
0
        return gnutls_assert_val(ret);
162
163
0
      return 0;
164
0
    }
165
0
  } else if (!vers->tls13_sem) {
166
    /* under TLS1.3 we want to pack the latest ticket, while that's
167
     * not the case in TLS1.2 or earlier. */
168
0
    if (gnutls_session_is_resumed(session)
169
0
        && session->internals.resumption_data.data) {
170
0
      ret =
171
0
          _gnutls_set_datum(data,
172
0
                session->
173
0
                internals.resumption_data.data,
174
0
                session->
175
0
                internals.resumption_data.size);
176
0
      if (ret < 0)
177
0
        return gnutls_assert_val(ret);
178
179
0
      return 0;
180
0
    }
181
0
  }
182
183
0
  if (!session->internals.resumable)
184
0
    return GNUTLS_E_INVALID_SESSION;
185
186
0
  ret = _gnutls_session_pack(session, data);
187
0
  if (ret < 0) {
188
0
    gnutls_assert();
189
0
    return ret;
190
0
  }
191
192
0
  return 0;
193
0
}
194
195
/**
196
 * gnutls_session_get_id:
197
 * @session: is a #gnutls_session_t type.
198
 * @session_id: is a pointer to space to hold the session id.
199
 * @session_id_size: initially should contain the maximum @session_id size and will be updated.
200
 *
201
 * Returns the TLS session identifier. The session ID is selected by the
202
 * server, and in older versions of TLS was a unique identifier shared
203
 * between client and server which was persistent across resumption.
204
 * In the latest version of TLS (1.3) or TLS with session tickets, the
205
 * notion of session identifiers is undefined and cannot be relied for uniquely
206
 * identifying sessions across client and server.
207
 *
208
 * In client side this function returns the identifier returned by the
209
 * server, and cannot be assumed to have any relation to session resumption.
210
 * In server side this function is guaranteed to return a persistent
211
 * identifier of the session since GnuTLS 3.6.4, which may not necessarily
212
 * map into the TLS session ID value. Prior to that version the value
213
 * could only be considered a persistent identifier, under TLS1.2 or earlier
214
 * and when no session tickets were in use.
215
 *
216
 * The session identifier value returned is always less than
217
 * %GNUTLS_MAX_SESSION_ID_SIZE.
218
 *
219
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
220
 *   an error code is returned.
221
 **/
222
int
223
gnutls_session_get_id(gnutls_session_t session,
224
          void *session_id, size_t *session_id_size)
225
0
{
226
0
  size_t given_session_id_size = *session_id_size;
227
228
0
  *session_id_size = session->security_parameters.session_id_size;
229
230
  /* just return the session size */
231
0
  if (session_id == NULL) {
232
0
    return 0;
233
0
  }
234
235
0
  if (given_session_id_size <
236
0
      session->security_parameters.session_id_size) {
237
0
    return GNUTLS_E_SHORT_MEMORY_BUFFER;
238
0
  }
239
240
0
  memcpy(session_id, &session->security_parameters.session_id,
241
0
         *session_id_size);
242
243
0
  return 0;
244
0
}
245
246
/**
247
 * gnutls_session_get_id2:
248
 * @session: is a #gnutls_session_t type.
249
 * @session_id: will point to the session ID.
250
 *
251
 * Returns the TLS session identifier. The session ID is selected by the
252
 * server, and in older versions of TLS was a unique identifier shared
253
 * between client and server which was persistent across resumption.
254
 * In the latest version of TLS (1.3) or TLS 1.2 with session tickets, the
255
 * notion of session identifiers is undefined and cannot be relied for uniquely
256
 * identifying sessions across client and server.
257
 *
258
 * In client side this function returns the identifier returned by the
259
 * server, and cannot be assumed to have any relation to session resumption.
260
 * In server side this function is guaranteed to return a persistent
261
 * identifier of the session since GnuTLS 3.6.4, which may not necessarily
262
 * map into the TLS session ID value. Prior to that version the value
263
 * could only be considered a persistent identifier, under TLS1.2 or earlier
264
 * and when no session tickets were in use.
265
 *
266
 * The session identifier value returned is always less than
267
 * %GNUTLS_MAX_SESSION_ID_SIZE and should be treated as constant.
268
 *
269
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
270
 *   an error code is returned.
271
 *
272
 * Since: 3.1.4
273
 **/
274
int
275
gnutls_session_get_id2(gnutls_session_t session, gnutls_datum_t * session_id)
276
0
{
277
0
  session_id->size = session->security_parameters.session_id_size;
278
0
  session_id->data = session->security_parameters.session_id;
279
280
0
  return 0;
281
0
}
282
283
/**
284
 * gnutls_session_set_data:
285
 * @session: is a #gnutls_session_t type.
286
 * @session_data: is a pointer to space to hold the session.
287
 * @session_data_size: is the session's size
288
 *
289
 * Sets all session parameters, in order to resume a previously
290
 * established session.  The session data given must be the one
291
 * returned by gnutls_session_get_data().  This function should be
292
 * called before gnutls_handshake().
293
 *
294
 * Keep in mind that session resuming is advisory. The server may
295
 * choose not to resume the session, thus a full handshake will be
296
 * performed.
297
 *
298
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
299
 *   an error code is returned.
300
 **/
301
int
302
gnutls_session_set_data(gnutls_session_t session,
303
      const void *session_data, size_t session_data_size)
304
0
{
305
0
  int ret;
306
0
  gnutls_datum_t psession;
307
308
0
  psession.data = (uint8_t *) session_data;
309
0
  psession.size = session_data_size;
310
311
0
  if (session_data == NULL || session_data_size == 0) {
312
0
    gnutls_assert();
313
0
    return GNUTLS_E_INVALID_REQUEST;
314
0
  }
315
316
  /* under TLS1.3 we always return some data on resumption when there
317
   * is no ticket in order to keep compatibility with existing apps */
318
0
  if (session_data_size == EMPTY_DATA_SIZE &&
319
0
      memcmp(session_data, EMPTY_DATA, EMPTY_DATA_SIZE) == 0) {
320
0
    return 0;
321
0
  }
322
323
0
  ret = _gnutls_session_unpack(session, &psession);
324
0
  if (ret < 0) {
325
0
    gnutls_assert();
326
0
    return ret;
327
0
  }
328
329
0
  session->internals.resumption_requested = 1;
330
331
0
  if (session->internals.resumption_data.data != NULL)
332
0
    gnutls_free(session->internals.resumption_data.data);
333
0
  ret =
334
0
      _gnutls_set_datum(&session->internals.resumption_data, session_data,
335
0
            session_data_size);
336
0
  if (ret < 0) {
337
0
    gnutls_assert();
338
0
    return ret;
339
0
  }
340
341
0
  return 0;
342
0
}
343
344
/**
345
 * gnutls_session_force_valid:
346
 * @session: is a #gnutls_session_t type.
347
 *
348
 * Clears the invalid flag in a session. That means
349
 * that sessions were corrupt or invalid data were received 
350
 * can be re-used. Use only when debugging or experimenting
351
 * with the TLS protocol. Should not be used in typical
352
 * applications.
353
 *
354
 **/
355
void gnutls_session_force_valid(gnutls_session_t session)
356
0
{
357
0
  session->internals.invalid_connection = 0;
358
0
}
359
360
0
#define DESC_SIZE 96
361
362
/**
363
 * gnutls_session_get_desc:
364
 * @session: is a gnutls session
365
 *
366
 * This function returns a string describing the current session.
367
 * The string is null terminated and allocated using gnutls_malloc().
368
 *
369
 * If initial negotiation is not complete when this function is called,
370
 * %NULL will be returned.
371
 *
372
 * Returns: a description of the protocols and algorithms in the current session.
373
 *
374
 * Since: 3.1.10
375
 **/
376
char *gnutls_session_get_desc(gnutls_session_t session)
377
0
{
378
0
  gnutls_kx_algorithm_t kx;
379
0
  const char *kx_str, *sign_str;
380
0
  gnutls_certificate_type_t ctype_client, ctype_server;
381
0
  char kx_name[64] = "";
382
0
  char proto_name[32];
383
0
  char _group_name[24];
384
0
  const char *group_name = NULL;
385
0
  int dh_bits = 0;
386
0
  unsigned mac_id;
387
0
  unsigned sign_algo;
388
0
  char *desc;
389
0
  const struct gnutls_group_entry_st *group = get_group(session);
390
0
  const version_entry_st *ver = get_version(session);
391
392
0
  if (session->internals.initial_negotiation_completed == 0)
393
0
    return NULL;
394
395
0
  kx = session->security_parameters.cs->kx_algorithm;
396
0
  if (group)
397
0
    group_name = group->name;
398
0
#if defined(ENABLE_DHE) || defined(ENABLE_ANON)
399
0
  if (group_name == NULL && _gnutls_kx_is_dhe(kx)) {
400
0
    dh_bits = gnutls_dh_get_prime_bits(session);
401
0
    if (dh_bits > 0)
402
0
      snprintf(_group_name, sizeof(_group_name), "CUSTOM%d",
403
0
         dh_bits);
404
0
    else
405
0
      snprintf(_group_name, sizeof(_group_name), "CUSTOM");
406
0
    group_name = _group_name;
407
0
  }
408
0
#endif
409
410
  /* Key exchange    - Signature algorithm */
411
  /* DHE-3072        - RSA-PSS-2048        */
412
  /* ECDHE-SECP256R1 - ECDSA-SECP256R1     */
413
414
0
  sign_algo = gnutls_sign_algorithm_get(session);
415
0
  sign_str = gnutls_sign_get_name(sign_algo);
416
417
0
  if (kx == 0 && ver->tls13_sem) { /* TLS 1.3 */
418
0
    if (session->internals.hsk_flags & HSK_PSK_SELECTED) {
419
0
      if (group) {
420
0
        if (group->pk == GNUTLS_PK_DH)
421
0
          snprintf(kx_name, sizeof(kx_name),
422
0
             "(DHE-PSK-%s)", group_name);
423
0
        else
424
0
          snprintf(kx_name, sizeof(kx_name),
425
0
             "(ECDHE-PSK-%s)", group_name);
426
0
      } else {
427
0
        snprintf(kx_name, sizeof(kx_name), "(PSK)");
428
0
      }
429
0
    } else if (group && sign_str) {
430
0
      if (group->curve)
431
0
        snprintf(kx_name, sizeof(kx_name),
432
0
           "(ECDHE-%s)-(%s)", group_name,
433
0
           sign_str);
434
0
      else
435
0
        snprintf(kx_name, sizeof(kx_name),
436
0
           "(DHE-%s)-(%s)", group_name, sign_str);
437
0
    }
438
0
  } else {
439
0
    kx_str = gnutls_kx_get_name(kx);
440
0
    if (kx_str == NULL) {
441
0
      gnutls_assert();
442
0
      return NULL;
443
0
    }
444
445
0
    if ((kx == GNUTLS_KX_ECDHE_ECDSA || kx == GNUTLS_KX_ECDHE_RSA ||
446
0
         kx == GNUTLS_KX_ECDHE_PSK) && group_name) {
447
0
      if (sign_str)
448
0
        snprintf(kx_name, sizeof(kx_name),
449
0
           "(ECDHE-%s)-(%s)", group_name,
450
0
           sign_str);
451
0
      else
452
0
        snprintf(kx_name, sizeof(kx_name), "(ECDHE-%s)",
453
0
           group_name);
454
0
    } else
455
0
        if ((kx == GNUTLS_KX_DHE_DSS || kx == GNUTLS_KX_DHE_RSA
456
0
       || kx == GNUTLS_KX_DHE_PSK) && group_name) {
457
0
      if (sign_str)
458
0
        snprintf(kx_name, sizeof(kx_name),
459
0
           "(DHE-%s)-(%s)", group_name, sign_str);
460
0
      else
461
0
        snprintf(kx_name, sizeof(kx_name), "(DHE-%s)",
462
0
           group_name);
463
0
    } else if (kx == GNUTLS_KX_RSA) {
464
      /* Possible enhancement: include the certificate bits */
465
0
      snprintf(kx_name, sizeof(kx_name), "(RSA)");
466
0
    } else {
467
0
      snprintf(kx_name, sizeof(kx_name), "(%s)", kx_str);
468
0
    }
469
0
  }
470
471
0
  if (are_alternative_cert_types_allowed(session)) {
472
    // Get certificate types
473
0
    ctype_client =
474
0
        get_certificate_type(session, GNUTLS_CTYPE_CLIENT);
475
0
    ctype_server =
476
0
        get_certificate_type(session, GNUTLS_CTYPE_SERVER);
477
478
0
    if (ctype_client == ctype_server) {
479
      // print proto version, client/server cert type
480
0
      snprintf(proto_name, sizeof(proto_name), "%s-%s",
481
0
         gnutls_protocol_get_name(get_num_version
482
0
                (session)),
483
0
         gnutls_certificate_type_get_name
484
0
         (ctype_client));
485
0
    } else {
486
      // print proto version, client cert type, server cert type
487
0
      snprintf(proto_name, sizeof(proto_name), "%s-%s-%s",
488
0
         gnutls_protocol_get_name(get_num_version
489
0
                (session)),
490
0
         gnutls_certificate_type_get_name(ctype_client),
491
0
         gnutls_certificate_type_get_name
492
0
         (ctype_server));
493
0
    }
494
0
  } else {   // Assumed default certificate type (X.509)
495
0
    snprintf(proto_name, sizeof(proto_name), "%s",
496
0
       gnutls_protocol_get_name(get_num_version(session)));
497
0
  }
498
499
0
  desc = gnutls_malloc(DESC_SIZE);
500
0
  if (desc == NULL)
501
0
    return NULL;
502
503
0
  mac_id = gnutls_mac_get(session);
504
0
  if (mac_id == GNUTLS_MAC_AEAD) { /* no need to print */
505
0
    snprintf(desc, DESC_SIZE,
506
0
       "(%s)-%s-(%s)",
507
0
       proto_name,
508
0
       kx_name,
509
0
       gnutls_cipher_get_name(gnutls_cipher_get(session)));
510
0
  } else {
511
0
    snprintf(desc, DESC_SIZE,
512
0
       "(%s)-%s-(%s)-(%s)",
513
0
       proto_name,
514
0
       kx_name,
515
0
       gnutls_cipher_get_name(gnutls_cipher_get(session)),
516
0
       gnutls_mac_get_name(mac_id));
517
0
  }
518
519
0
  return desc;
520
0
}
521
522
/**
523
 * gnutls_session_set_id:
524
 * @session: is a #gnutls_session_t type.
525
 * @sid: the session identifier
526
 *
527
 * This function sets the session ID to be used in a client hello.
528
 * This is a function intended for exceptional uses. Do not use this
529
 * function unless you are implementing a custom protocol.
530
 *
531
 * To set session resumption parameters use gnutls_session_set_data() instead.
532
 *
533
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
534
 *   an error code is returned.
535
 *
536
 * Since: 3.2.1
537
 **/
538
int gnutls_session_set_id(gnutls_session_t session, const gnutls_datum_t * sid)
539
0
{
540
0
  if (session->security_parameters.entity == GNUTLS_SERVER ||
541
0
      sid->size > GNUTLS_MAX_SESSION_ID_SIZE)
542
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
543
544
0
  memset(&session->internals.resumed_security_parameters, 0,
545
0
         sizeof(session->internals.resumed_security_parameters));
546
547
0
  session->internals.resumed_security_parameters.session_id_size =
548
0
      sid->size;
549
0
  memcpy(session->internals.resumed_security_parameters.session_id,
550
0
         sid->data, sid->size);
551
552
0
  return 0;
553
0
}