|
Packit |
549fdc |
/*
|
|
Packit |
549fdc |
* Copyright (C) 2002-2016 Free Software Foundation, Inc.
|
|
Packit |
549fdc |
* Copyright (C) 2014-2016 Nikos Mavrogiannopoulos
|
|
Packit |
549fdc |
* Copyright (C) 2015-2016 Red Hat, Inc.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Author: Nikos Mavrogiannopoulos
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This file is part of GnuTLS.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* The GnuTLS is free software; you can redistribute it and/or
|
|
Packit |
549fdc |
* modify it under the terms of the GNU Lesser General Public License
|
|
Packit |
549fdc |
* as published by the Free Software Foundation; either version 2.1 of
|
|
Packit |
549fdc |
* the License, or (at your option) any later version.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This library is distributed in the hope that it will be useful, but
|
|
Packit |
549fdc |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
549fdc |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
549fdc |
* Lesser General Public License for more details.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* You should have received a copy of the GNU Lesser General Public License
|
|
Packit |
549fdc |
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* Functions to manipulate the session (gnutls_int.h), and some other stuff
|
|
Packit |
549fdc |
* are included here. The file's name is traditionally gnutls_state even if the
|
|
Packit |
549fdc |
* state has been renamed to session.
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
#include "gnutls_int.h"
|
|
Packit |
549fdc |
#include "errors.h"
|
|
Packit |
549fdc |
#include <auth.h>
|
|
Packit |
549fdc |
#include <num.h>
|
|
Packit |
549fdc |
#include <datum.h>
|
|
Packit |
549fdc |
#include <db.h>
|
|
Packit |
549fdc |
#include <record.h>
|
|
Packit |
549fdc |
#include <handshake.h>
|
|
Packit |
549fdc |
#include <dh.h>
|
|
Packit |
549fdc |
#include <buffers.h>
|
|
Packit |
549fdc |
#include <mbuffers.h>
|
|
Packit |
549fdc |
#include <state.h>
|
|
Packit |
549fdc |
#include <constate.h>
|
|
Packit |
549fdc |
#include <auth/cert.h>
|
|
Packit |
549fdc |
#include <auth/anon.h>
|
|
Packit |
549fdc |
#include <auth/psk.h>
|
|
Packit |
549fdc |
#include <algorithms.h>
|
|
Packit |
549fdc |
#include <extensions.h>
|
|
Packit |
549fdc |
#include <system.h>
|
|
Packit |
549fdc |
#include <random.h>
|
|
Packit |
549fdc |
#include <fips.h>
|
|
Packit |
549fdc |
#include <intprops.h>
|
|
Packit |
549fdc |
#include <gnutls/dtls.h>
|
|
Packit |
549fdc |
#include "dtls.h"
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* These should really be static, but src/tests.c calls them. Make
|
|
Packit |
549fdc |
them public functions? */
|
|
Packit |
549fdc |
void
|
|
Packit |
549fdc |
_gnutls_rsa_pms_set_version(gnutls_session_t session,
|
|
Packit |
549fdc |
unsigned char major, unsigned char minor);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_cipher_get:
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Get currently used cipher.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: the currently used cipher, a #gnutls_cipher_algorithm_t
|
|
Packit |
549fdc |
* type.
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
gnutls_cipher_algorithm_t gnutls_cipher_get(gnutls_session_t session)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
record_parameters_st *record_params;
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
_gnutls_epoch_get(session, EPOCH_READ_CURRENT, &record_params);
|
|
Packit |
549fdc |
if (ret < 0)
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_CIPHER_NULL);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return record_params->cipher->id;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_certificate_type_get:
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* The certificate type is by default X.509, unless it is negotiated
|
|
Packit |
549fdc |
* as a TLS extension.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: the currently used #gnutls_certificate_type_t certificate
|
|
Packit |
549fdc |
* type.
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
gnutls_certificate_type_t
|
|
Packit |
549fdc |
gnutls_certificate_type_get(gnutls_session_t session)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
return session->security_parameters.cert_type;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_kx_get:
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Get currently used key exchange algorithm.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: the key exchange algorithm used in the last handshake, a
|
|
Packit |
549fdc |
* #gnutls_kx_algorithm_t value.
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
gnutls_kx_algorithm_t gnutls_kx_get(gnutls_session_t session)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
if (session->security_parameters.cs == 0)
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
return session->security_parameters.cs->kx_algorithm;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_mac_get:
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Get currently used MAC algorithm.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: the currently used mac algorithm, a
|
|
Packit |
549fdc |
* #gnutls_mac_algorithm_t value.
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
gnutls_mac_algorithm_t gnutls_mac_get(gnutls_session_t session)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
record_parameters_st *record_params;
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
_gnutls_epoch_get(session, EPOCH_READ_CURRENT, &record_params);
|
|
Packit |
549fdc |
if (ret < 0)
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_MAC_NULL);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return record_params->mac->id;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_compression_get:
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Get currently used compression algorithm.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: the currently used compression method, a
|
|
Packit |
549fdc |
* #gnutls_compression_method_t value.
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
gnutls_compression_method_t
|
|
Packit |
549fdc |
gnutls_compression_get(gnutls_session_t session)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
return GNUTLS_COMP_NULL;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
static void deinit_keys(gnutls_session_t session)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
gnutls_pk_params_release(&session->key.ecdh_params);
|
|
Packit |
549fdc |
gnutls_pk_params_release(&session->key.dh_params);
|
|
Packit |
549fdc |
zrelease_temp_mpi_key(&session->key.ecdh_x);
|
|
Packit |
549fdc |
zrelease_temp_mpi_key(&session->key.ecdh_y);
|
|
Packit |
549fdc |
_gnutls_free_temp_key_datum(&session->key.ecdhx);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
zrelease_temp_mpi_key(&session->key.client_Y);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* SRP */
|
|
Packit |
549fdc |
zrelease_temp_mpi_key(&session->key.srp_p);
|
|
Packit |
549fdc |
zrelease_temp_mpi_key(&session->key.srp_g);
|
|
Packit |
549fdc |
zrelease_temp_mpi_key(&session->key.srp_key);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
zrelease_temp_mpi_key(&session->key.u);
|
|
Packit |
549fdc |
zrelease_temp_mpi_key(&session->key.a);
|
|
Packit |
549fdc |
zrelease_temp_mpi_key(&session->key.x);
|
|
Packit |
549fdc |
zrelease_temp_mpi_key(&session->key.A);
|
|
Packit |
549fdc |
zrelease_temp_mpi_key(&session->key.B);
|
|
Packit |
549fdc |
zrelease_temp_mpi_key(&session->key.b);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_gnutls_free_temp_key_datum(&session->key.key);
|
|
Packit |
549fdc |
_gnutls_free_temp_key_datum(&session->key.key);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* An internal version of _gnutls_handshake_internal_state_clear(),
|
|
Packit |
549fdc |
* it will not attempt to deallocate, only initialize */
|
|
Packit |
549fdc |
static void handshake_internal_state_clear1(gnutls_session_t session)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
/* by default no selected certificate */
|
|
Packit |
549fdc |
session->internals.adv_version_major = 0;
|
|
Packit |
549fdc |
session->internals.adv_version_minor = 0;
|
|
Packit |
549fdc |
session->internals.direction = 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* use out of band data for the last
|
|
Packit |
549fdc |
* handshake messages received.
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
session->internals.last_handshake_in = -1;
|
|
Packit |
549fdc |
session->internals.last_handshake_out = -1;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
session->internals.resumable = RESUME_TRUE;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
session->internals.handshake_suspicious_loops = 0;
|
|
Packit |
549fdc |
session->internals.dtls.hsk_read_seq = 0;
|
|
Packit |
549fdc |
session->internals.dtls.hsk_write_seq = 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
session->internals.have_ffdhe = 0;
|
|
Packit |
549fdc |
session->internals.cand_ec_group = 0;
|
|
Packit |
549fdc |
session->internals.cand_dh_group = 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* This function will clear all the variables in internals
|
|
Packit |
549fdc |
* structure within the session, which depend on the current handshake.
|
|
Packit |
549fdc |
* This is used to allow further handshakes.
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
void _gnutls_handshake_internal_state_clear(gnutls_session_t session)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
handshake_internal_state_clear1(session);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_gnutls_handshake_hash_buffers_clear(session);
|
|
Packit |
549fdc |
deinit_keys(session);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_gnutls_epoch_gc(session);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
session->internals.handshake_endtime = 0;
|
|
Packit |
549fdc |
session->internals.handshake_in_progress = 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
session->internals.tfo.connect_addrlen = 0;
|
|
Packit |
549fdc |
session->internals.tfo.connect_only = 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_init:
|
|
Packit |
549fdc |
* @session: is a pointer to a #gnutls_session_t type.
|
|
Packit |
549fdc |
* @flags: indicate if this session is to be used for server or client.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function initializes the provided session. Every
|
|
Packit |
549fdc |
* session must be initialized before use, and must be deinitialized
|
|
Packit |
549fdc |
* after used by calling gnutls_deinit().
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* @flags can be any combination of flags from %gnutls_init_flags_t.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Note that since version 3.1.2 this function enables some common
|
|
Packit |
549fdc |
* TLS extensions such as session tickets and OCSP certificate status
|
|
Packit |
549fdc |
* request in client side by default. To prevent that use the %GNUTLS_NO_EXTENSIONS
|
|
Packit |
549fdc |
* flag.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: %GNUTLS_E_SUCCESS on success, or an error code.
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int gnutls_init(gnutls_session_t * session, unsigned int flags)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
FAIL_IF_LIB_ERROR;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
*session = gnutls_calloc(1, sizeof(struct gnutls_session_int));
|
|
Packit |
549fdc |
if (*session == NULL)
|
|
Packit |
549fdc |
return GNUTLS_E_MEMORY_ERROR;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = _gnutls_epoch_new(*session, 1, NULL);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_free(*session);
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
_gnutls_epoch_bump(*session);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
(*session)->security_parameters.entity =
|
|
Packit |
549fdc |
(flags & GNUTLS_SERVER ? GNUTLS_SERVER : GNUTLS_CLIENT);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* the default certificate type for TLS */
|
|
Packit |
549fdc |
(*session)->security_parameters.cert_type = DEFAULT_CERT_TYPE;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* Initialize buffers */
|
|
Packit |
549fdc |
_gnutls_buffer_init(&(*session)->internals.handshake_hash_buffer);
|
|
Packit |
549fdc |
_gnutls_buffer_init(&(*session)->internals.hb_remote_data);
|
|
Packit |
549fdc |
_gnutls_buffer_init(&(*session)->internals.hb_local_data);
|
|
Packit |
549fdc |
_gnutls_buffer_init(&(*session)->internals.record_presend_buffer);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_mbuffer_head_init(&(*session)->internals.record_buffer);
|
|
Packit |
549fdc |
_mbuffer_head_init(&(*session)->internals.record_send_buffer);
|
|
Packit |
549fdc |
_mbuffer_head_init(&(*session)->internals.record_recv_buffer);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_mbuffer_head_init(&(*session)->internals.handshake_send_buffer);
|
|
Packit |
549fdc |
_gnutls_handshake_recv_buffer_init(*session);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
(*session)->internals.expire_time = DEFAULT_EXPIRE_TIME; /* one hour default */
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
gnutls_handshake_set_max_packet_length((*session),
|
|
Packit |
549fdc |
MAX_HANDSHAKE_PACKET_SIZE);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* set the socket pointers to -1;
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
(*session)->internals.transport_recv_ptr =
|
|
Packit |
549fdc |
(gnutls_transport_ptr_t) - 1;
|
|
Packit |
549fdc |
(*session)->internals.transport_send_ptr =
|
|
Packit |
549fdc |
(gnutls_transport_ptr_t) - 1;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* set the default maximum record size for TLS
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
(*session)->security_parameters.max_record_recv_size =
|
|
Packit |
549fdc |
DEFAULT_MAX_RECORD_SIZE;
|
|
Packit |
549fdc |
(*session)->security_parameters.max_record_send_size =
|
|
Packit |
549fdc |
DEFAULT_MAX_RECORD_SIZE;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* everything else not initialized here is initialized
|
|
Packit |
549fdc |
* as NULL or 0. This is why calloc is used.
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
handshake_internal_state_clear1(*session);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
#ifdef HAVE_WRITEV
|
|
Packit |
549fdc |
#ifdef MSG_NOSIGNAL
|
|
Packit |
549fdc |
if (flags & GNUTLS_NO_SIGNAL)
|
|
Packit |
549fdc |
gnutls_transport_set_vec_push_function(*session, system_writev_nosignal);
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
#endif
|
|
Packit |
549fdc |
gnutls_transport_set_vec_push_function(*session, system_writev);
|
|
Packit |
549fdc |
#else
|
|
Packit |
549fdc |
gnutls_transport_set_push_function(*session, system_write);
|
|
Packit |
549fdc |
#endif
|
|
Packit |
549fdc |
(*session)->internals.pull_timeout_func = gnutls_system_recv_timeout;
|
|
Packit |
549fdc |
(*session)->internals.pull_func = system_read;
|
|
Packit |
549fdc |
(*session)->internals.errno_func = system_errno;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* heartbeat timeouts */
|
|
Packit |
549fdc |
(*session)->internals.hb_retrans_timeout_ms = 1000;
|
|
Packit |
549fdc |
(*session)->internals.hb_total_timeout_ms = 60000;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (flags & GNUTLS_DATAGRAM) {
|
|
Packit |
549fdc |
(*session)->internals.dtls.mtu = DTLS_DEFAULT_MTU;
|
|
Packit |
549fdc |
(*session)->internals.transport = GNUTLS_DGRAM;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
gnutls_dtls_set_timeouts(*session, DTLS_RETRANS_TIMEOUT, 60000);
|
|
Packit |
549fdc |
} else {
|
|
Packit |
549fdc |
(*session)->internals.transport = GNUTLS_STREAM;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* Enable useful extensions */
|
|
Packit |
549fdc |
if ((flags & GNUTLS_CLIENT) && !(flags & GNUTLS_NO_EXTENSIONS)) {
|
|
Packit |
549fdc |
#ifdef ENABLE_SESSION_TICKETS
|
|
Packit |
549fdc |
if (!(flags & GNUTLS_NO_TICKETS))
|
|
Packit |
549fdc |
gnutls_session_ticket_enable_client(*session);
|
|
Packit |
549fdc |
#endif
|
|
Packit |
549fdc |
#ifdef ENABLE_OCSP
|
|
Packit |
549fdc |
gnutls_ocsp_status_request_enable_client(*session, NULL, 0,
|
|
Packit |
549fdc |
NULL);
|
|
Packit |
549fdc |
#endif
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
(*session)->internals.flags = flags;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* returns RESUME_FALSE or RESUME_TRUE.
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
int _gnutls_session_is_resumable(gnutls_session_t session)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
return session->internals.resumable;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_deinit:
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function clears all buffers associated with the @session.
|
|
Packit |
549fdc |
* This function will also remove session data from the session
|
|
Packit |
549fdc |
* database if the session was terminated abnormally.
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
void gnutls_deinit(gnutls_session_t session)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
unsigned int i;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (session == NULL)
|
|
Packit |
549fdc |
return;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* remove auth info firstly */
|
|
Packit |
549fdc |
_gnutls_free_auth_info(session);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_gnutls_handshake_internal_state_clear(session);
|
|
Packit |
549fdc |
_gnutls_handshake_io_buffer_clear(session);
|
|
Packit |
549fdc |
_gnutls_ext_free_session_data(session);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
for (i = 0; i < MAX_EPOCH_INDEX; i++)
|
|
Packit |
549fdc |
if (session->record_parameters[i] != NULL) {
|
|
Packit |
549fdc |
_gnutls_epoch_free(session,
|
|
Packit |
549fdc |
session->record_parameters[i]);
|
|
Packit |
549fdc |
session->record_parameters[i] = NULL;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_gnutls_buffer_clear(&session->internals.handshake_hash_buffer);
|
|
Packit |
549fdc |
_gnutls_buffer_clear(&session->internals.hb_remote_data);
|
|
Packit |
549fdc |
_gnutls_buffer_clear(&session->internals.hb_local_data);
|
|
Packit |
549fdc |
_gnutls_buffer_clear(&session->internals.record_presend_buffer);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_mbuffer_head_clear(&session->internals.record_buffer);
|
|
Packit |
549fdc |
_mbuffer_head_clear(&session->internals.record_recv_buffer);
|
|
Packit |
549fdc |
_mbuffer_head_clear(&session->internals.record_send_buffer);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_gnutls_free_datum(&session->internals.resumption_data);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
gnutls_free(session->internals.rexts);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
gnutls_free(session->internals.rsup);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
gnutls_credentials_clear(session);
|
|
Packit |
549fdc |
_gnutls_selected_certs_deinit(session);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* we rely on priorities' internal reference counting */
|
|
Packit |
549fdc |
gnutls_priority_deinit(session->internals.priorities);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
gnutls_free(session);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
int _gnutls_dh_set_peer_public(gnutls_session_t session, bigint_t public)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
dh_info_st *dh;
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
switch (gnutls_auth_get_type(session)) {
|
|
Packit |
549fdc |
case GNUTLS_CRD_ANON:
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
anon_auth_info_t info;
|
|
Packit |
549fdc |
info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON);
|
|
Packit |
549fdc |
if (info == NULL)
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
dh = &info->dh;
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
case GNUTLS_CRD_PSK:
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
psk_auth_info_t info;
|
|
Packit |
549fdc |
info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
|
|
Packit |
549fdc |
if (info == NULL)
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
dh = &info->dh;
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
case GNUTLS_CRD_CERTIFICATE:
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
cert_auth_info_t info;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
|
|
Packit |
549fdc |
if (info == NULL)
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
dh = &info->dh;
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
default:
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (dh->public_key.data)
|
|
Packit |
549fdc |
_gnutls_free_datum(&dh->public_key);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = _gnutls_mpi_dprint_lz(public, &dh->public_key);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
int _gnutls_dh_set_secret_bits(gnutls_session_t session, unsigned bits)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
switch (gnutls_auth_get_type(session)) {
|
|
Packit |
549fdc |
case GNUTLS_CRD_ANON:
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
anon_auth_info_t info;
|
|
Packit |
549fdc |
info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON);
|
|
Packit |
549fdc |
if (info == NULL)
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
|
Packit |
549fdc |
info->dh.secret_bits = bits;
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
case GNUTLS_CRD_PSK:
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
psk_auth_info_t info;
|
|
Packit |
549fdc |
info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
|
|
Packit |
549fdc |
if (info == NULL)
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
|
Packit |
549fdc |
info->dh.secret_bits = bits;
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
case GNUTLS_CRD_CERTIFICATE:
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
cert_auth_info_t info;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
|
|
Packit |
549fdc |
if (info == NULL)
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
info->dh.secret_bits = bits;
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
default:
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* Sets the prime and the generator in the auth info structure.
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
_gnutls_dh_save_group(gnutls_session_t session, bigint_t gen,
|
|
Packit |
549fdc |
bigint_t prime)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
dh_info_st *dh;
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
switch (gnutls_auth_get_type(session)) {
|
|
Packit |
549fdc |
case GNUTLS_CRD_ANON:
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
anon_auth_info_t info;
|
|
Packit |
549fdc |
info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON);
|
|
Packit |
549fdc |
if (info == NULL)
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
dh = &info->dh;
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
case GNUTLS_CRD_PSK:
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
psk_auth_info_t info;
|
|
Packit |
549fdc |
info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
|
|
Packit |
549fdc |
if (info == NULL)
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
dh = &info->dh;
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
case GNUTLS_CRD_CERTIFICATE:
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
cert_auth_info_t info;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
|
|
Packit |
549fdc |
if (info == NULL)
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
dh = &info->dh;
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
default:
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (dh->prime.data)
|
|
Packit |
549fdc |
_gnutls_free_datum(&dh->prime);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (dh->generator.data)
|
|
Packit |
549fdc |
_gnutls_free_datum(&dh->generator);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* prime
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
ret = _gnutls_mpi_dprint_lz(prime, &dh->prime);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* generator
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
ret = _gnutls_mpi_dprint_lz(gen, &dh->generator);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
_gnutls_free_datum(&dh->prime);
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_certificate_send_x509_rdn_sequence:
|
|
Packit |
549fdc |
* @session: a #gnutls_session_t type.
|
|
Packit |
549fdc |
* @status: is 0 or 1
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* If status is non zero, this function will order gnutls not to send
|
|
Packit |
549fdc |
* the rdnSequence in the certificate request message. That is the
|
|
Packit |
549fdc |
* server will not advertise its trusted CAs to the peer. If status
|
|
Packit |
549fdc |
* is zero then the default behaviour will take effect, which is to
|
|
Packit |
549fdc |
* advertise the server's trusted CAs.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function has no effect in clients, and in authentication
|
|
Packit |
549fdc |
* methods other than certificate with X.509 certificates.
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
void
|
|
Packit |
549fdc |
gnutls_certificate_send_x509_rdn_sequence(gnutls_session_t session,
|
|
Packit |
549fdc |
int status)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
session->internals.ignore_rdn_sequence = status;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/*-
|
|
Packit |
549fdc |
* _gnutls_record_set_default_version - Used to set the default version for the first record packet
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type.
|
|
Packit |
549fdc |
* @major: is a tls major version
|
|
Packit |
549fdc |
* @minor: is a tls minor version
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function sets the default version that we will use in the first
|
|
Packit |
549fdc |
* record packet (client hello). This function is only useful to people
|
|
Packit |
549fdc |
* that know TLS internals and want to debug other implementations.
|
|
Packit |
549fdc |
-*/
|
|
Packit |
549fdc |
void
|
|
Packit |
549fdc |
_gnutls_record_set_default_version(gnutls_session_t session,
|
|
Packit |
549fdc |
unsigned char major,
|
|
Packit |
549fdc |
unsigned char minor)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
session->internals.default_record_version[0] = major;
|
|
Packit |
549fdc |
session->internals.default_record_version[1] = minor;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/*-
|
|
Packit |
549fdc |
* _gnutls_hello_set_default_version - Used to set the default version for the first record packet
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type.
|
|
Packit |
549fdc |
* @major: is a tls major version
|
|
Packit |
549fdc |
* @minor: is a tls minor version
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function sets the default version that we will use in the first
|
|
Packit |
549fdc |
* record packet (client hello). This function is only useful to people
|
|
Packit |
549fdc |
* that know TLS internals and want to debug other implementations.
|
|
Packit |
549fdc |
-*/
|
|
Packit |
549fdc |
void
|
|
Packit |
549fdc |
_gnutls_hello_set_default_version(gnutls_session_t session,
|
|
Packit |
549fdc |
unsigned char major,
|
|
Packit |
549fdc |
unsigned char minor)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
session->internals.default_hello_version[0] = major;
|
|
Packit |
549fdc |
session->internals.default_hello_version[1] = minor;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_handshake_set_private_extensions:
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type.
|
|
Packit |
549fdc |
* @allow: is an integer (0 or 1)
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function will enable or disable the use of private cipher
|
|
Packit |
549fdc |
* suites (the ones that start with 0xFF). By default or if @allow
|
|
Packit |
549fdc |
* is 0 then these cipher suites will not be advertised nor used.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Currently GnuTLS does not include such cipher-suites or
|
|
Packit |
549fdc |
* compression algorithms.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Enabling the private ciphersuites when talking to other than
|
|
Packit |
549fdc |
* gnutls servers and clients may cause interoperability problems.
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
void
|
|
Packit |
549fdc |
gnutls_handshake_set_private_extensions(gnutls_session_t session,
|
|
Packit |
549fdc |
int allow)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
/* we have no private extensions */
|
|
Packit |
549fdc |
return;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_session_is_resumed:
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Check whether session is resumed or not.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: non zero if this session is resumed, or a zero if this is
|
|
Packit |
549fdc |
* a new session.
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int gnutls_session_is_resumed(gnutls_session_t session)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
if (session->security_parameters.entity == GNUTLS_CLIENT) {
|
|
Packit |
549fdc |
if (session->security_parameters.session_id_size > 0 &&
|
|
Packit |
549fdc |
session->security_parameters.session_id_size ==
|
|
Packit |
549fdc |
session->internals.resumed_security_parameters.
|
|
Packit |
549fdc |
session_id_size
|
|
Packit |
549fdc |
&& memcmp(session->security_parameters.session_id,
|
|
Packit |
549fdc |
session->
|
|
Packit |
549fdc |
internals.resumed_security_parameters.
|
|
Packit |
549fdc |
session_id,
|
|
Packit |
549fdc |
session->security_parameters.
|
|
Packit |
549fdc |
session_id_size) == 0)
|
|
Packit |
549fdc |
return 1;
|
|
Packit |
549fdc |
} else {
|
|
Packit |
549fdc |
if (session->internals.resumed != RESUME_FALSE)
|
|
Packit |
549fdc |
return 1;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_session_resumption_requested:
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Check whether the client has asked for session resumption.
|
|
Packit |
549fdc |
* This function is valid only on server side.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: non zero if session resumption was asked, or a zero if not.
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int gnutls_session_resumption_requested(gnutls_session_t session)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
if (session->security_parameters.entity == GNUTLS_CLIENT) {
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
} else {
|
|
Packit |
549fdc |
return session->internals.resumption_requested;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/*-
|
|
Packit |
549fdc |
* _gnutls_session_is_psk - Used to check whether this session uses PSK kx
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function will return non zero if this session uses a PSK key
|
|
Packit |
549fdc |
* exchange algorithm.
|
|
Packit |
549fdc |
-*/
|
|
Packit |
549fdc |
int _gnutls_session_is_psk(gnutls_session_t session)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
gnutls_kx_algorithm_t kx;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
kx = session->security_parameters.cs->kx_algorithm;
|
|
Packit |
549fdc |
if (kx == GNUTLS_KX_PSK || kx == GNUTLS_KX_DHE_PSK
|
|
Packit |
549fdc |
|| kx == GNUTLS_KX_RSA_PSK)
|
|
Packit |
549fdc |
return 1;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/*-
|
|
Packit |
549fdc |
* _gnutls_session_is_ecc - Used to check whether this session uses ECC kx
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function will return non zero if this session uses an elliptic
|
|
Packit |
549fdc |
* curves key exchange exchange algorithm.
|
|
Packit |
549fdc |
-*/
|
|
Packit |
549fdc |
int _gnutls_session_is_ecc(gnutls_session_t session)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
gnutls_kx_algorithm_t kx;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* We get the key exchange algorithm through the ciphersuite because
|
|
Packit |
549fdc |
* the negotiated key exchange might not have been set yet.
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
kx = session->security_parameters.cs->kx_algorithm;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return _gnutls_kx_is_ecc(kx);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_session_get_ptr:
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Get user pointer for session. Useful in callbacks. This is the
|
|
Packit |
549fdc |
* pointer set with gnutls_session_set_ptr().
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: the user given pointer from the session structure, or
|
|
Packit |
549fdc |
* %NULL if it was never set.
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
void *gnutls_session_get_ptr(gnutls_session_t session)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
return session->internals.user_ptr;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_session_set_ptr:
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type.
|
|
Packit |
549fdc |
* @ptr: is the user pointer
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function will set (associate) the user given pointer @ptr to
|
|
Packit |
549fdc |
* the session structure. This pointer can be accessed with
|
|
Packit |
549fdc |
* gnutls_session_get_ptr().
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
void gnutls_session_set_ptr(gnutls_session_t session, void *ptr)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
session->internals.user_ptr = ptr;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_session_set_verify_function:
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type.
|
|
Packit |
549fdc |
* @func: is the callback function
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function sets a callback to be called when peer's certificate
|
|
Packit |
549fdc |
* has been received in order to verify it on receipt rather than
|
|
Packit |
549fdc |
* doing after the handshake is completed. This overrides any callback
|
|
Packit |
549fdc |
* set using gnutls_certificate_set_verify_function().
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* The callback's function prototype is:
|
|
Packit |
549fdc |
* int (*callback)(gnutls_session_t);
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* If the callback function is provided then gnutls will call it, in the
|
|
Packit |
549fdc |
* handshake, just after the certificate message has been received.
|
|
Packit |
549fdc |
* To verify or obtain the certificate the gnutls_certificate_verify_peers2(),
|
|
Packit |
549fdc |
* gnutls_certificate_type_get(), gnutls_certificate_get_peers() functions
|
|
Packit |
549fdc |
* can be used.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* The callback function should return 0 for the handshake to continue
|
|
Packit |
549fdc |
* or non-zero to terminate.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Since: 3.4.6
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
void
|
|
Packit |
549fdc |
gnutls_session_set_verify_function
|
|
Packit |
549fdc |
(gnutls_session_t session,
|
|
Packit |
549fdc |
gnutls_certificate_verify_function * func)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
session->internals.verify_callback = func;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_record_get_direction:
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function provides information about the internals of the
|
|
Packit |
549fdc |
* record protocol and is only useful if a prior gnutls function call,
|
|
Packit |
549fdc |
* e.g. gnutls_handshake(), was interrupted for some reason. That
|
|
Packit |
549fdc |
* is, if a function returned %GNUTLS_E_INTERRUPTED or
|
|
Packit |
549fdc |
* %GNUTLS_E_AGAIN. In such a case, you might want to call select()
|
|
Packit |
549fdc |
* or poll() before restoring the interrupted gnutls function.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function's output is unreliable if you are using the same
|
|
Packit |
549fdc |
* @session in different threads, for sending and receiving.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: 0 if interrupted while trying to read data, or 1 while trying to write data.
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int gnutls_record_get_direction(gnutls_session_t session)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
return session->internals.direction;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/*-
|
|
Packit |
549fdc |
* _gnutls_rsa_pms_set_version - Sets a version to be used at the RSA PMS
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type.
|
|
Packit |
549fdc |
* @major: is the major version to use
|
|
Packit |
549fdc |
* @minor: is the minor version to use
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function will set the given version number to be used at the
|
|
Packit |
549fdc |
* RSA PMS secret. This is only useful to clients, which want to
|
|
Packit |
549fdc |
* test server's capabilities.
|
|
Packit |
549fdc |
-*/
|
|
Packit |
549fdc |
void
|
|
Packit |
549fdc |
_gnutls_rsa_pms_set_version(gnutls_session_t session,
|
|
Packit |
549fdc |
unsigned char major, unsigned char minor)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
session->internals.rsa_pms_version[0] = major;
|
|
Packit |
549fdc |
session->internals.rsa_pms_version[1] = minor;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_handshake_set_post_client_hello_function:
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type.
|
|
Packit |
549fdc |
* @func: is the function to be called
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function will set a callback to be called after the client
|
|
Packit |
549fdc |
* hello has been received (callback valid in server side only). This
|
|
Packit |
549fdc |
* allows the server to adjust settings based on received extensions.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Those settings could be ciphersuites, requesting certificate, or
|
|
Packit |
549fdc |
* anything else except for version negotiation (this is done before
|
|
Packit |
549fdc |
* the hello message is parsed).
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This callback must return 0 on success or a gnutls error code to
|
|
Packit |
549fdc |
* terminate the handshake.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Since GnuTLS 3.3.5 the callback is
|
|
Packit |
549fdc |
* allowed to return %GNUTLS_E_AGAIN or %GNUTLS_E_INTERRUPTED to
|
|
Packit |
549fdc |
* put the handshake on hold. In that case gnutls_handshake()
|
|
Packit |
549fdc |
* will return %GNUTLS_E_INTERRUPTED and can be resumed when needed.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Warning: You should not use this function to terminate the
|
|
Packit |
549fdc |
* handshake based on client input unless you know what you are
|
|
Packit |
549fdc |
* doing. Before the handshake is finished there is no way to know if
|
|
Packit |
549fdc |
* there is a man-in-the-middle attack being performed.
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
void
|
|
Packit |
549fdc |
gnutls_handshake_set_post_client_hello_function(gnutls_session_t session,
|
|
Packit |
549fdc |
gnutls_handshake_simple_hook_func func)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
session->internals.user_hello_func = func;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_session_enable_compatibility_mode:
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function can be used to disable certain (security) features in
|
|
Packit |
549fdc |
* TLS in order to maintain maximum compatibility with buggy
|
|
Packit |
549fdc |
* clients. Because several trade-offs with security are enabled,
|
|
Packit |
549fdc |
* if required they will be reported through the audit subsystem.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Normally only servers that require maximum compatibility with
|
|
Packit |
549fdc |
* everything out there, need to call this function.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Note that this function must be called after any call to gnutls_priority
|
|
Packit |
549fdc |
* functions.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Since: 2.1.4
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
void gnutls_session_enable_compatibility_mode(gnutls_session_t session)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
ENABLE_COMPAT(&session->internals);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_session_channel_binding:
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type.
|
|
Packit |
549fdc |
* @cbtype: an #gnutls_channel_binding_t enumeration type
|
|
Packit |
549fdc |
* @cb: output buffer array with data
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Extract given channel binding data of the @cbtype (e.g.,
|
|
Packit |
549fdc |
* %GNUTLS_CB_TLS_UNIQUE) type.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: %GNUTLS_E_SUCCESS on success,
|
|
Packit |
549fdc |
* %GNUTLS_E_UNIMPLEMENTED_FEATURE if the @cbtype is unsupported,
|
|
Packit |
549fdc |
* %GNUTLS_E_CHANNEL_BINDING_NOT_AVAILABLE if the data is not
|
|
Packit |
549fdc |
* currently available, or an error code.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Since: 2.12.0
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
gnutls_session_channel_binding(gnutls_session_t session,
|
|
Packit |
549fdc |
gnutls_channel_binding_t cbtype,
|
|
Packit |
549fdc |
gnutls_datum_t * cb)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
if (cbtype != GNUTLS_CB_TLS_UNIQUE)
|
|
Packit |
549fdc |
return GNUTLS_E_UNIMPLEMENTED_FEATURE;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (!session->internals.initial_negotiation_completed)
|
|
Packit |
549fdc |
return GNUTLS_E_CHANNEL_BINDING_NOT_AVAILABLE;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
cb->size = session->internals.cb_tls_unique_len;
|
|
Packit |
549fdc |
cb->data = gnutls_malloc(cb->size);
|
|
Packit |
549fdc |
if (cb->data == NULL)
|
|
Packit |
549fdc |
return GNUTLS_E_MEMORY_ERROR;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
memcpy(cb->data, session->internals.cb_tls_unique, cb->size);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_ecc_curve_get:
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns the currently used elliptic curve for key exchange. Only valid
|
|
Packit |
549fdc |
* when using an elliptic curve ciphersuite.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: the currently used curve, a #gnutls_ecc_curve_t
|
|
Packit |
549fdc |
* type.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Since: 3.0
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
gnutls_ecc_curve_t gnutls_ecc_curve_get(gnutls_session_t session)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
const gnutls_group_entry_st *e;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
e = get_group(session);
|
|
Packit |
549fdc |
if (e == NULL || e->curve == 0)
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
return e->curve;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_group_get:
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns the currently used group for key exchange. Only valid
|
|
Packit |
549fdc |
* when using an elliptic curve or DH ciphersuite.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: the currently used group, a #gnutls_group_t
|
|
Packit |
549fdc |
* type.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Since: 3.6.0
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
gnutls_group_t gnutls_group_get(gnutls_session_t session)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
const gnutls_group_entry_st *e;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
e = get_group(session);
|
|
Packit |
549fdc |
if (e == NULL)
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
return e->id;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_protocol_get_version:
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Get TLS version, a #gnutls_protocol_t value.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: The version of the currently used protocol.
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
gnutls_protocol_t gnutls_protocol_get_version(gnutls_session_t session)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
return get_num_version(session);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_session_get_random:
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type.
|
|
Packit |
549fdc |
* @client: the client part of the random
|
|
Packit |
549fdc |
* @server: the server part of the random
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function returns pointers to the client and server
|
|
Packit |
549fdc |
* random fields used in the TLS handshake. The pointers are
|
|
Packit |
549fdc |
* not to be modified or deallocated.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* If a client random value has not yet been established, the output
|
|
Packit |
549fdc |
* will be garbage.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Since: 3.0
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
void
|
|
Packit |
549fdc |
gnutls_session_get_random(gnutls_session_t session,
|
|
Packit |
549fdc |
gnutls_datum_t * client, gnutls_datum_t * server)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
if (client) {
|
|
Packit |
549fdc |
client->data = session->security_parameters.client_random;
|
|
Packit |
549fdc |
client->size =
|
|
Packit |
549fdc |
sizeof(session->security_parameters.client_random);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (server) {
|
|
Packit |
549fdc |
server->data = session->security_parameters.server_random;
|
|
Packit |
549fdc |
server->size =
|
|
Packit |
549fdc |
sizeof(session->security_parameters.server_random);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_session_get_master_secret:
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type.
|
|
Packit |
549fdc |
* @secret: the session's master secret
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function returns pointers to the master secret
|
|
Packit |
549fdc |
* used in the TLS session. The pointers are not to be modified or deallocated.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Since: 3.5.0
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
void
|
|
Packit |
549fdc |
gnutls_session_get_master_secret(gnutls_session_t session, gnutls_datum_t *secret)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
secret->data = session->security_parameters.master_secret;
|
|
Packit |
549fdc |
secret->size = sizeof(session->security_parameters.master_secret);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
unsigned int timespec_sub_ms(struct timespec *a, struct timespec *b)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
time_t dsecs;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
dsecs = a->tv_sec - b->tv_sec;
|
|
Packit |
549fdc |
if (!INT_MULTIPLY_OVERFLOW(dsecs, 1000)) {
|
|
Packit |
549fdc |
return (dsecs*1000 + (a->tv_nsec - b->tv_nsec) / (1000 * 1000));
|
|
Packit |
549fdc |
} else {
|
|
Packit |
549fdc |
return UINT_MAX;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_handshake_set_random:
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type.
|
|
Packit |
549fdc |
* @random: a random value of 32-bytes
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function will explicitly set the server or client hello
|
|
Packit |
549fdc |
* random value in the subsequent TLS handshake. The random value
|
|
Packit |
549fdc |
* should be a 32-byte value.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Note that this function should not normally be used as gnutls
|
|
Packit |
549fdc |
* will select automatically a random value for the handshake.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function should not be used when resuming a session.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: %GNUTLS_E_SUCCESS on success, or an error code.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Since 3.1.9
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
gnutls_handshake_set_random(gnutls_session_t session,
|
|
Packit |
549fdc |
const gnutls_datum_t * random)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
if (random->size != GNUTLS_RANDOM_SIZE)
|
|
Packit |
549fdc |
return GNUTLS_E_INVALID_REQUEST;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
session->internals.sc_random_set = 1;
|
|
Packit |
549fdc |
if (session->security_parameters.entity == GNUTLS_CLIENT)
|
|
Packit |
549fdc |
memcpy(session->internals.resumed_security_parameters.
|
|
Packit |
549fdc |
client_random, random->data, random->size);
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
memcpy(session->internals.resumed_security_parameters.
|
|
Packit |
549fdc |
server_random, random->data, random->size);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_handshake_set_hook_function:
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type
|
|
Packit |
549fdc |
* @htype: the %gnutls_handshake_description_t of the message to hook at
|
|
Packit |
549fdc |
* @when: %GNUTLS_HOOK_* depending on when the hook function should be called
|
|
Packit |
549fdc |
* @func: is the function to be called
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function will set a callback to be called after or before the specified
|
|
Packit |
549fdc |
* handshake message has been received or generated. This is a
|
|
Packit |
549fdc |
* generalization of gnutls_handshake_set_post_client_hello_function().
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* To call the hook function prior to the message being generated or processed
|
|
Packit |
549fdc |
* use %GNUTLS_HOOK_PRE as @when parameter, %GNUTLS_HOOK_POST to call
|
|
Packit |
549fdc |
* after, and %GNUTLS_HOOK_BOTH for both cases.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This callback must return 0 on success or a gnutls error code to
|
|
Packit |
549fdc |
* terminate the handshake.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* To hook at all handshake messages use an @htype of %GNUTLS_HANDSHAKE_ANY.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Warning: You should not use this function to terminate the
|
|
Packit |
549fdc |
* handshake based on client input unless you know what you are
|
|
Packit |
549fdc |
* doing. Before the handshake is finished there is no way to know if
|
|
Packit |
549fdc |
* there is a man-in-the-middle attack being performed.
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
void
|
|
Packit |
549fdc |
gnutls_handshake_set_hook_function(gnutls_session_t session,
|
|
Packit |
549fdc |
unsigned int htype,
|
|
Packit |
549fdc |
int when,
|
|
Packit |
549fdc |
gnutls_handshake_hook_func func)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
session->internals.h_hook = func;
|
|
Packit |
549fdc |
session->internals.h_type = htype;
|
|
Packit |
549fdc |
session->internals.h_post = when;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_record_get_state:
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type
|
|
Packit |
549fdc |
* @read: if non-zero the read parameters are returned, otherwise the write
|
|
Packit |
549fdc |
* @mac_key: the key used for MAC (if a MAC is used)
|
|
Packit |
549fdc |
* @IV: the initialization vector or nonce used
|
|
Packit |
549fdc |
* @cipher_key: the cipher key
|
|
Packit |
549fdc |
* @seq_number: A 64-bit sequence number
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function will return the parameters of the current record state.
|
|
Packit |
549fdc |
* These are only useful to be provided to an external off-loading device
|
|
Packit |
549fdc |
* or subsystem.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* In that case, to sync the state you must call gnutls_record_set_state().
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: %GNUTLS_E_SUCCESS on success, or an error code.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Since 3.4.0
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
gnutls_record_get_state(gnutls_session_t session,
|
|
Packit |
549fdc |
unsigned read,
|
|
Packit |
549fdc |
gnutls_datum_t *mac_key,
|
|
Packit |
549fdc |
gnutls_datum_t *IV,
|
|
Packit |
549fdc |
gnutls_datum_t *cipher_key,
|
|
Packit |
549fdc |
unsigned char seq_number[8])
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
record_parameters_st *record_params;
|
|
Packit |
549fdc |
record_state_st *record_state;
|
|
Packit |
549fdc |
unsigned int epoch;
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (read)
|
|
Packit |
549fdc |
epoch = EPOCH_READ_CURRENT;
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
epoch = EPOCH_WRITE_CURRENT;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = _gnutls_epoch_get(session, epoch, &record_params);
|
|
Packit |
549fdc |
if (ret < 0)
|
|
Packit |
549fdc |
return gnutls_assert_val(ret);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (!record_params->initialized)
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (read)
|
|
Packit |
549fdc |
record_state = &record_params->read;
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
record_state = &record_params->write;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (mac_key)
|
|
Packit |
549fdc |
memcpy(mac_key, &record_state->mac_secret, sizeof(gnutls_datum_t));
|
|
Packit |
549fdc |
if (IV)
|
|
Packit |
549fdc |
memcpy(IV, &record_state->IV, sizeof(gnutls_datum_t));
|
|
Packit |
549fdc |
if (cipher_key)
|
|
Packit |
549fdc |
memcpy(cipher_key, &record_state->key, sizeof(gnutls_datum_t));
|
|
Packit |
549fdc |
if (seq_number)
|
|
Packit |
549fdc |
memcpy(seq_number, UINT64DATA(record_state->sequence_number), 8);
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_record_set_state:
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type
|
|
Packit |
549fdc |
* @read: if non-zero the read parameters are returned, otherwise the write
|
|
Packit |
549fdc |
* @seq_number: A 64-bit sequence number
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function will set the sequence number in the current record state.
|
|
Packit |
549fdc |
* This function is useful if sending and receiving are offloaded from
|
|
Packit |
549fdc |
* gnutls. That is, if gnutls_record_get_state() was used.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: %GNUTLS_E_SUCCESS on success, or an error code.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Since 3.4.0
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
gnutls_record_set_state(gnutls_session_t session,
|
|
Packit |
549fdc |
unsigned read,
|
|
Packit |
549fdc |
unsigned char seq_number[8])
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
record_parameters_st *record_params;
|
|
Packit |
549fdc |
record_state_st *record_state;
|
|
Packit |
549fdc |
int epoch, ret;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (read)
|
|
Packit |
549fdc |
epoch = EPOCH_READ_CURRENT;
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
epoch = EPOCH_WRITE_CURRENT;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = _gnutls_epoch_get(session, epoch, &record_params);
|
|
Packit |
549fdc |
if (ret < 0)
|
|
Packit |
549fdc |
return gnutls_assert_val(ret);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (!record_params->initialized)
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (read)
|
|
Packit |
549fdc |
record_state = &record_params->read;
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
record_state = &record_params->write;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
memcpy(UINT64DATA(record_state->sequence_number), seq_number, 8);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (IS_DTLS(session)) {
|
|
Packit |
549fdc |
_dtls_reset_window(record_params);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_session_get_flags:
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function will return a series (ORed) of flags, applicable
|
|
Packit |
549fdc |
* for the current session.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This replaces individual informational functions such as
|
|
Packit |
549fdc |
* gnutls_safe_renegotiation_status(), gnutls_session_ext_master_secret_status(),
|
|
Packit |
549fdc |
* etc.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: An ORed sequence of flags (see %gnutls_session_flags_t)
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Since: 3.5.0
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
unsigned gnutls_session_get_flags(gnutls_session_t session)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
unsigned flags = 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (gnutls_safe_renegotiation_status(session))
|
|
Packit |
549fdc |
flags |= GNUTLS_SFLAGS_SAFE_RENEGOTIATION;
|
|
Packit |
549fdc |
if (gnutls_session_ext_master_secret_status(session))
|
|
Packit |
549fdc |
flags |= GNUTLS_SFLAGS_EXT_MASTER_SECRET;
|
|
Packit |
549fdc |
if (gnutls_session_etm_status(session))
|
|
Packit |
549fdc |
flags |= GNUTLS_SFLAGS_ETM;
|
|
Packit |
549fdc |
if (gnutls_heartbeat_allowed(session, GNUTLS_HB_LOCAL_ALLOWED_TO_SEND))
|
|
Packit |
549fdc |
flags |= GNUTLS_SFLAGS_HB_LOCAL_SEND;
|
|
Packit |
549fdc |
if (gnutls_heartbeat_allowed(session, GNUTLS_HB_PEER_ALLOWED_TO_SEND))
|
|
Packit |
549fdc |
flags |= GNUTLS_SFLAGS_HB_PEER_SEND;
|
|
Packit |
549fdc |
if (session->internals.false_start_used)
|
|
Packit |
549fdc |
flags |= GNUTLS_SFLAGS_FALSE_START;
|
|
Packit |
549fdc |
if (session->internals.used_ffdhe)
|
|
Packit |
549fdc |
flags |= GNUTLS_SFLAGS_RFC7919;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return flags;
|
|
Packit |
549fdc |
}
|