Line data Source code
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 330 : gnutls_session_get_data(gnutls_session_t session,
49 : void *session_data, size_t * session_data_size)
50 : {
51 :
52 330 : gnutls_datum_t psession;
53 330 : int ret;
54 :
55 330 : ret = gnutls_session_get_data2(session, &psession);
56 330 : if (ret < 0) {
57 0 : gnutls_assert();
58 0 : return ret;
59 : }
60 :
61 330 : if (psession.size > *session_data_size) {
62 30 : *session_data_size = psession.size;
63 30 : ret = GNUTLS_E_SHORT_MEMORY_BUFFER;
64 30 : goto error;
65 : }
66 300 : *session_data_size = psession.size;
67 :
68 300 : if (session_data != NULL)
69 165 : memcpy(session_data, psession.data, psession.size);
70 :
71 : ret = 0;
72 :
73 330 : error:
74 330 : _gnutls_free_datum(&psession);
75 330 : return ret;
76 : }
77 :
78 : #define EMPTY_DATA "\x00\x00\x00\x00"
79 : #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
122 495 : gnutls_session_get_data2(gnutls_session_t session, gnutls_datum_t *data)
123 : {
124 495 : const version_entry_st *vers = get_version(session);
125 495 : int ret;
126 :
127 495 : if (data == NULL || vers == NULL) {
128 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
129 : }
130 :
131 495 : if (vers->tls13_sem && !(session->internals.hsk_flags & HSK_TICKET_RECEIVED)) {
132 44 : unsigned ertt = session->internals.ertt;
133 : /* use our estimation of round-trip + some time for the server to calculate
134 : * the value(s). */
135 44 : 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 44 : if (NO_TIMEOUT_FUNC_SET(session) || (session->internals.flags & GNUTLS_NONBLOCK)) {
140 1 : if (!(session->internals.flags & GNUTLS_NONBLOCK))
141 1 : _gnutls_debug_log("TLS1.3 works efficiently if a callback with gnutls_transport_set_pull_timeout_function() is set\n");
142 : } else {
143 : /* wait for a message with timeout */
144 43 : ret = _gnutls_recv_in_buffers(session, GNUTLS_APPLICATION_DATA, -1, ertt);
145 43 : if (ret < 0 && (gnutls_error_is_fatal(ret) && ret != GNUTLS_E_TIMEDOUT)) {
146 0 : return gnutls_assert_val(ret);
147 : }
148 : }
149 :
150 44 : if (!(session->internals.hsk_flags & HSK_TICKET_RECEIVED)) {
151 1 : ret = _gnutls_set_datum(data, EMPTY_DATA, EMPTY_DATA_SIZE);
152 1 : if (ret < 0)
153 0 : return gnutls_assert_val(ret);
154 :
155 : return 0;
156 : }
157 451 : } else if (!vers->tls13_sem) {
158 : /* under TLS1.3 we want to pack the latest ticket, while that's
159 : * not the case in TLS1.2 or earlier. */
160 442 : if (gnutls_session_is_resumed(session) && session->internals.resumption_data.data) {
161 22 : ret = _gnutls_set_datum(data, session->internals.resumption_data.data, session->internals.resumption_data.size);
162 22 : if (ret < 0)
163 0 : return gnutls_assert_val(ret);
164 :
165 : return 0;
166 : }
167 : }
168 :
169 472 : if (session->internals.resumable == RESUME_FALSE)
170 : return GNUTLS_E_INVALID_SESSION;
171 :
172 472 : ret = _gnutls_session_pack(session, data);
173 472 : if (ret < 0) {
174 1 : gnutls_assert();
175 1 : return ret;
176 : }
177 :
178 : return 0;
179 : }
180 :
181 :
182 : /**
183 : * gnutls_session_get_id:
184 : * @session: is a #gnutls_session_t type.
185 : * @session_id: is a pointer to space to hold the session id.
186 : * @session_id_size: initially should contain the maximum @session_id size and will be updated.
187 : *
188 : * Returns the TLS session identifier. The session ID is selected by the
189 : * server, and in older versions of TLS was a unique identifier shared
190 : * between client and server which was persistent across resumption.
191 : * In the latest version of TLS (1.3) or TLS with session tickets, the
192 : * notion of session identifiers is undefined and cannot be relied for uniquely
193 : * identifying sessions across client and server.
194 : *
195 : * In client side this function returns the identifier returned by the
196 : * server, and cannot be assumed to have any relation to session resumption.
197 : * In server side this function is guaranteed to return a persistent
198 : * identifier of the session since GnuTLS 3.6.4, which may not necessarily
199 : * map into the TLS session ID value. Prior to that version the value
200 : * could only be considered a persistent identifier, under TLS1.2 or earlier
201 : * and when no session tickets were in use.
202 : *
203 : * The session identifier value returned is always less than
204 : * %GNUTLS_MAX_SESSION_ID_SIZE.
205 : *
206 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
207 : * an error code is returned.
208 : **/
209 : int
210 7742 : gnutls_session_get_id(gnutls_session_t session,
211 : void *session_id, size_t * session_id_size)
212 : {
213 7742 : size_t given_session_id_size = *session_id_size;
214 :
215 7742 : *session_id_size = session->security_parameters.session_id_size;
216 :
217 : /* just return the session size */
218 7742 : if (session_id == NULL) {
219 : return 0;
220 : }
221 :
222 7742 : if (given_session_id_size <
223 7742 : session->security_parameters.session_id_size) {
224 : return GNUTLS_E_SHORT_MEMORY_BUFFER;
225 : }
226 :
227 7742 : memcpy(session_id, &session->security_parameters.session_id,
228 : *session_id_size);
229 :
230 7742 : return 0;
231 : }
232 :
233 : /**
234 : * gnutls_session_get_id2:
235 : * @session: is a #gnutls_session_t type.
236 : * @session_id: will point to the session ID.
237 : *
238 : * Returns the TLS session identifier. The session ID is selected by the
239 : * server, and in older versions of TLS was a unique identifier shared
240 : * between client and server which was persistent across resumption.
241 : * In the latest version of TLS (1.3) or TLS 1.2 with session tickets, the
242 : * notion of session identifiers is undefined and cannot be relied for uniquely
243 : * identifying sessions across client and server.
244 : *
245 : * In client side this function returns the identifier returned by the
246 : * server, and cannot be assumed to have any relation to session resumption.
247 : * In server side this function is guaranteed to return a persistent
248 : * identifier of the session since GnuTLS 3.6.4, which may not necessarily
249 : * map into the TLS session ID value. Prior to that version the value
250 : * could only be considered a persistent identifier, under TLS1.2 or earlier
251 : * and when no session tickets were in use.
252 : *
253 : * The session identifier value returned is always less than
254 : * %GNUTLS_MAX_SESSION_ID_SIZE and should be treated as constant.
255 : *
256 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
257 : * an error code is returned.
258 : *
259 : * Since: 3.1.4
260 : **/
261 : int
262 0 : gnutls_session_get_id2(gnutls_session_t session,
263 : gnutls_datum_t * session_id)
264 : {
265 0 : session_id->size = session->security_parameters.session_id_size;
266 0 : session_id->data = session->security_parameters.session_id;
267 :
268 0 : return 0;
269 : }
270 :
271 : /**
272 : * gnutls_session_set_data:
273 : * @session: is a #gnutls_session_t type.
274 : * @session_data: is a pointer to space to hold the session.
275 : * @session_data_size: is the session's size
276 : *
277 : * Sets all session parameters, in order to resume a previously
278 : * established session. The session data given must be the one
279 : * returned by gnutls_session_get_data(). This function should be
280 : * called before gnutls_handshake().
281 : *
282 : * Keep in mind that session resuming is advisory. The server may
283 : * choose not to resume the session, thus a full handshake will be
284 : * performed.
285 : *
286 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
287 : * an error code is returned.
288 : **/
289 : int
290 908 : gnutls_session_set_data(gnutls_session_t session,
291 : const void *session_data, size_t session_data_size)
292 : {
293 908 : int ret;
294 908 : gnutls_datum_t psession;
295 :
296 908 : psession.data = (uint8_t *) session_data;
297 908 : psession.size = session_data_size;
298 :
299 908 : if (session_data == NULL || session_data_size == 0) {
300 0 : gnutls_assert();
301 0 : return GNUTLS_E_INVALID_REQUEST;
302 : }
303 :
304 : /* under TLS1.3 we always return some data on resumption when there
305 : * is no ticket in order to keep compatibility with existing apps */
306 908 : if (session_data_size == EMPTY_DATA_SIZE &&
307 0 : memcmp(session_data, EMPTY_DATA, EMPTY_DATA_SIZE) == 0) {
308 : return 0;
309 : }
310 :
311 908 : ret = _gnutls_session_unpack(session, &psession);
312 908 : if (ret < 0) {
313 12 : gnutls_assert();
314 12 : return ret;
315 : }
316 :
317 896 : session->internals.resumption_requested = 1;
318 :
319 896 : if (session->internals.resumption_data.data != NULL)
320 0 : gnutls_free(session->internals.resumption_data.data);
321 896 : ret = _gnutls_set_datum(&session->internals.resumption_data, session_data, session_data_size);
322 896 : if (ret < 0) {
323 0 : gnutls_assert();
324 0 : return ret;
325 : }
326 :
327 : return 0;
328 : }
329 :
330 : /**
331 : * gnutls_session_force_valid:
332 : * @session: is a #gnutls_session_t type.
333 : *
334 : * Clears the invalid flag in a session. That means
335 : * that sessions were corrupt or invalid data were received
336 : * can be re-used. Use only when debugging or experimenting
337 : * with the TLS protocol. Should not be used in typical
338 : * applications.
339 : *
340 : **/
341 1049 : void gnutls_session_force_valid(gnutls_session_t session)
342 : {
343 1049 : session->internals.invalid_connection = 0;
344 1049 : }
345 :
346 : #define DESC_SIZE 96
347 :
348 : /**
349 : * gnutls_session_get_desc:
350 : * @session: is a gnutls session
351 : *
352 : * This function returns a string describing the current session.
353 : * The string is null terminated and allocated using gnutls_malloc().
354 : *
355 : * If initial negotiation is not complete when this function is called,
356 : * %NULL will be returned.
357 : *
358 : * Returns: a description of the protocols and algorithms in the current session.
359 : *
360 : * Since: 3.1.10
361 : **/
362 8552 : char *gnutls_session_get_desc(gnutls_session_t session)
363 : {
364 8552 : gnutls_kx_algorithm_t kx;
365 8552 : const char *kx_str, *sign_str;
366 8552 : gnutls_certificate_type_t ctype_client, ctype_server;
367 8552 : char kx_name[64] = "";
368 8552 : char proto_name[32];
369 8552 : char _group_name[24];
370 8552 : const char *group_name = NULL;
371 8552 : int dh_bits = 0;
372 8552 : unsigned mac_id;
373 8552 : unsigned sign_algo;
374 8552 : char *desc;
375 8552 : const struct gnutls_group_entry_st *group = get_group(session);
376 8552 : const version_entry_st *ver = get_version(session);
377 :
378 8552 : if (session->internals.initial_negotiation_completed == 0)
379 : return NULL;
380 :
381 8552 : kx = session->security_parameters.cs->kx_algorithm;
382 8552 : if (group)
383 4742 : group_name = group->name;
384 : #if defined(ENABLE_DHE) || defined(ENABLE_ANON)
385 4742 : if (group_name == NULL && _gnutls_kx_is_dhe(kx)) {
386 1381 : dh_bits = gnutls_dh_get_prime_bits(session);
387 1381 : if (dh_bits > 0)
388 1040 : snprintf(_group_name, sizeof(_group_name), "CUSTOM%u", dh_bits);
389 : else
390 341 : snprintf(_group_name, sizeof(_group_name), "CUSTOM");
391 : group_name = _group_name;
392 : }
393 : #endif
394 :
395 : /* Key exchange - Signature algorithm */
396 : /* DHE-3072 - RSA-PSS-2048 */
397 : /* ECDHE-SECP256R1 - ECDSA-SECP256R1 */
398 :
399 8552 : sign_algo = gnutls_sign_algorithm_get(session);
400 8552 : sign_str = gnutls_sign_get_name(sign_algo);
401 :
402 8552 : if (kx == 0 && ver->tls13_sem) { /* TLS 1.3 */
403 4360 : if (session->internals.hsk_flags & HSK_PSK_SELECTED) {
404 1202 : if (group) {
405 412 : if (group->pk == GNUTLS_PK_DH)
406 222 : snprintf(kx_name, sizeof(kx_name), "(DHE-PSK-%s)",
407 : group_name);
408 : else
409 190 : snprintf(kx_name, sizeof(kx_name), "(ECDHE-PSK-%s)",
410 : group_name);
411 : } else {
412 790 : snprintf(kx_name, sizeof(kx_name), "(PSK)");
413 : }
414 3158 : } else if (group && sign_str) {
415 3158 : if (group->curve)
416 1751 : snprintf(kx_name, sizeof(kx_name), "(ECDHE-%s)-(%s)",
417 : group_name, sign_str);
418 : else
419 1407 : snprintf(kx_name, sizeof(kx_name), "(DHE-%s)-(%s)",
420 : group_name, sign_str);
421 : }
422 : } else {
423 4192 : kx_str = gnutls_kx_get_name(kx);
424 4192 : if (kx_str == NULL) {
425 0 : gnutls_assert();
426 0 : return NULL;
427 : }
428 :
429 4192 : if ((kx == GNUTLS_KX_ECDHE_ECDSA || kx == GNUTLS_KX_ECDHE_RSA ||
430 832 : kx == GNUTLS_KX_ECDHE_PSK) && group_name) {
431 830 : if (sign_str)
432 523 : snprintf(kx_name, sizeof(kx_name), "(ECDHE-%s)-(%s)",
433 : group_name, sign_str);
434 : else
435 307 : snprintf(kx_name, sizeof(kx_name), "(ECDHE-%s)",
436 : group_name);
437 3362 : } else if ((kx == GNUTLS_KX_DHE_DSS || kx == GNUTLS_KX_DHE_RSA ||
438 3362 : kx == GNUTLS_KX_DHE_PSK) && group_name) {
439 1720 : if (sign_str)
440 1412 : snprintf(kx_name, sizeof(kx_name), "(DHE-%s)-(%s)", group_name, sign_str);
441 : else
442 308 : snprintf(kx_name, sizeof(kx_name), "(DHE-%s)", group_name);
443 1642 : } else if (kx == GNUTLS_KX_RSA) {
444 : /* Possible enhancement: include the certificate bits */
445 1260 : snprintf(kx_name, sizeof(kx_name), "(RSA)");
446 : } else {
447 382 : snprintf(kx_name, sizeof(kx_name), "(%s)",
448 : kx_str);
449 : }
450 : }
451 :
452 8552 : if (are_alternative_cert_types_allowed(session)) {
453 : // Get certificate types
454 6357 : ctype_client = get_certificate_type(session, GNUTLS_CTYPE_CLIENT);
455 6357 : ctype_server = get_certificate_type(session, GNUTLS_CTYPE_SERVER);
456 :
457 6357 : if (ctype_client == ctype_server) {
458 : // print proto version, client/server cert type
459 6352 : snprintf(proto_name, sizeof(proto_name), "%s-%s",
460 6352 : gnutls_protocol_get_name(get_num_version(session)),
461 : gnutls_certificate_type_get_name(ctype_client));
462 : } else {
463 : // print proto version, client cert type, server cert type
464 5 : snprintf(proto_name, sizeof(proto_name), "%s-%s-%s",
465 5 : gnutls_protocol_get_name(get_num_version(session)),
466 : gnutls_certificate_type_get_name(ctype_client),
467 : gnutls_certificate_type_get_name(ctype_server));
468 : }
469 : } else { // Assumed default certificate type (X.509)
470 2195 : snprintf(proto_name, sizeof(proto_name), "%s",
471 2195 : gnutls_protocol_get_name(get_num_version(session)));
472 : }
473 :
474 8552 : desc = gnutls_malloc(DESC_SIZE);
475 8552 : if (desc == NULL)
476 : return NULL;
477 :
478 8552 : mac_id = gnutls_mac_get(session);
479 8552 : if (mac_id == GNUTLS_MAC_AEAD) { /* no need to print */
480 5841 : snprintf(desc, DESC_SIZE,
481 : "(%s)-%s-(%s)",
482 : proto_name,
483 : kx_name,
484 : gnutls_cipher_get_name(gnutls_cipher_get(session)));
485 : } else {
486 2711 : snprintf(desc, DESC_SIZE,
487 : "(%s)-%s-(%s)-(%s)",
488 : proto_name,
489 : kx_name,
490 : gnutls_cipher_get_name(gnutls_cipher_get(session)),
491 : gnutls_mac_get_name(mac_id));
492 : }
493 :
494 : return desc;
495 : }
496 :
497 : /**
498 : * gnutls_session_set_id:
499 : * @session: is a #gnutls_session_t type.
500 : * @sid: the session identifier
501 : *
502 : * This function sets the session ID to be used in a client hello.
503 : * This is a function intended for exceptional uses. Do not use this
504 : * function unless you are implementing a custom protocol.
505 : *
506 : * To set session resumption parameters use gnutls_session_set_data() instead.
507 : *
508 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
509 : * an error code is returned.
510 : *
511 : * Since: 3.2.1
512 : **/
513 : int
514 2 : gnutls_session_set_id(gnutls_session_t session, const gnutls_datum_t * sid)
515 : {
516 2 : if (session->security_parameters.entity == GNUTLS_SERVER ||
517 2 : sid->size > GNUTLS_MAX_SESSION_ID_SIZE)
518 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
519 :
520 2 : memset(&session->internals.resumed_security_parameters, 0,
521 : sizeof(session->internals.resumed_security_parameters));
522 :
523 2 : session->internals.resumed_security_parameters.session_id_size =
524 2 : sid->size;
525 2 : memcpy(session->internals.resumed_security_parameters.session_id,
526 2 : sid->data, sid->size);
527 :
528 2 : return 0;
529 : }
|