diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2015-08-23 19:19:45 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2015-08-23 19:27:01 +0200 |
commit | f84d8c0d536a1b6a160ddceadf7fade8d7b2edaa (patch) | |
tree | ea8ded214d074604f4bbfbd9ed31a07beb48f21d /lib/session_pack.c | |
parent | 172ae7efd99ce30d3bdfc2a35e0335687ef70a0f (diff) | |
download | gnutls-f84d8c0d536a1b6a160ddceadf7fade8d7b2edaa.tar.gz |
Removed the 'gnutls_' prefix from files to simplify file naming
Diffstat (limited to 'lib/session_pack.c')
-rw-r--r-- | lib/session_pack.c | 980 |
1 files changed, 980 insertions, 0 deletions
diff --git a/lib/session_pack.c b/lib/session_pack.c new file mode 100644 index 0000000000..19229b70d9 --- /dev/null +++ b/lib/session_pack.c @@ -0,0 +1,980 @@ +/* + * Copyright (C) 2000-2012 Free Software Foundation, Inc. + * + * Author: Nikos Mavrogiannopoulos + * + * This file is part of GnuTLS. + * + * The GnuTLS is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +/* Contains functions that are supposed to pack and unpack session data, + * before and after they are sent to the database backend. + */ + +#include "gnutls_int.h" +#ifdef ENABLE_SRP +#include <auth/srp_kx.h> +#endif +#ifdef ENABLE_PSK +#include <auth/psk.h> +#endif +#include <auth/anon.h> +#include <auth/cert.h> +#include "errors.h" +#include <auth.h> +#include <session_pack.h> +#include <datum.h> +#include <num.h> +#include <extensions.h> +#include <constate.h> +#include <algorithms.h> +#include <state.h> +#include <db.h> + +static int pack_certificate_auth_info(gnutls_session_t, + gnutls_buffer_st * packed_session); +static int unpack_certificate_auth_info(gnutls_session_t, + gnutls_buffer_st * packed_session); + +static int unpack_srp_auth_info(gnutls_session_t session, + gnutls_buffer_st * packed_session); +static int pack_srp_auth_info(gnutls_session_t session, + gnutls_buffer_st * packed_session); + +static int unpack_psk_auth_info(gnutls_session_t session, + gnutls_buffer_st * packed_session); +static int pack_psk_auth_info(gnutls_session_t session, + gnutls_buffer_st * packed_session); + +static int unpack_anon_auth_info(gnutls_session_t session, + gnutls_buffer_st * packed_session); +static int pack_anon_auth_info(gnutls_session_t session, + gnutls_buffer_st * packed_session); + +static int unpack_security_parameters(gnutls_session_t session, + gnutls_buffer_st * packed_session); +static int pack_security_parameters(gnutls_session_t session, + gnutls_buffer_st * packed_session); + + +/* Since auth_info structures contain malloced data, this function + * is required in order to pack these structures in a vector in + * order to store them to the DB. + * + * packed_session will contain the session data. + * + * The data will be in a platform independent format. + */ +int +_gnutls_session_pack(gnutls_session_t session, + gnutls_datum_t * packed_session) +{ + int ret; + gnutls_buffer_st sb; + uint8_t id; + + if (packed_session == NULL) { + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } + + _gnutls_buffer_init(&sb); + + + id = gnutls_auth_get_type(session); + + BUFFER_APPEND_NUM(&sb, PACKED_SESSION_MAGIC); + BUFFER_APPEND_NUM(&sb, session->security_parameters.timestamp); + BUFFER_APPEND(&sb, &id, 1); + + switch (id) { +#ifdef ENABLE_SRP + case GNUTLS_CRD_SRP: + ret = pack_srp_auth_info(session, &sb); + if (ret < 0) { + gnutls_assert(); + goto fail; + } + break; +#endif +#ifdef ENABLE_PSK + case GNUTLS_CRD_PSK: + ret = pack_psk_auth_info(session, &sb); + if (ret < 0) { + gnutls_assert(); + goto fail; + } + break; +#endif +#ifdef ENABLE_ANON + case GNUTLS_CRD_ANON: + ret = pack_anon_auth_info(session, &sb); + if (ret < 0) { + gnutls_assert(); + goto fail; + } + break; +#endif + case GNUTLS_CRD_CERTIFICATE: + ret = pack_certificate_auth_info(session, &sb); + if (ret < 0) { + gnutls_assert(); + goto fail; + } + break; + default: + return GNUTLS_E_INTERNAL_ERROR; + + } + + /* Auth_info structures copied. Now copy security_parameters_st. + * packed_session must have allocated space for the security parameters. + */ + ret = pack_security_parameters(session, &sb); + if (ret < 0) { + gnutls_assert(); + goto fail; + } + + ret = _gnutls_ext_pack(session, &sb); + if (ret < 0) { + gnutls_assert(); + goto fail; + } + + return _gnutls_buffer_to_datum(&sb, packed_session, 0); + + fail: + _gnutls_buffer_clear(&sb); + return ret; +} + + +/* Load session data from a buffer. + */ +int +_gnutls_session_unpack(gnutls_session_t session, + const gnutls_datum_t * packed_session) +{ + int ret; + gnutls_buffer_st sb; + uint32_t magic; + uint8_t id; + + _gnutls_buffer_init(&sb); + + if (packed_session == NULL || packed_session->size == 0) { + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } + + ret = + _gnutls_buffer_append_data(&sb, packed_session->data, + packed_session->size); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + if (session->key.auth_info != NULL) { + _gnutls_free_auth_info(session); + } + + BUFFER_POP_NUM(&sb, magic); + if (magic != PACKED_SESSION_MAGIC) { + ret = gnutls_assert_val(GNUTLS_E_DB_ERROR); + goto error; + } + + BUFFER_POP_NUM(&sb, + session->internals.resumed_security_parameters. + timestamp); + BUFFER_POP(&sb, &id, 1); + + switch (id) { +#ifdef ENABLE_SRP + case GNUTLS_CRD_SRP: + ret = unpack_srp_auth_info(session, &sb); + if (ret < 0) { + gnutls_assert(); + goto error; + } + break; +#endif +#ifdef ENABLE_PSK + case GNUTLS_CRD_PSK: + ret = unpack_psk_auth_info(session, &sb); + if (ret < 0) { + gnutls_assert(); + goto error; + } + break; +#endif +#ifdef ENABLE_ANON + case GNUTLS_CRD_ANON: + ret = unpack_anon_auth_info(session, &sb); + if (ret < 0) { + gnutls_assert(); + return ret; + } + break; +#endif + case GNUTLS_CRD_CERTIFICATE: + ret = unpack_certificate_auth_info(session, &sb); + if (ret < 0) { + gnutls_assert(); + goto error; + } + break; + default: + gnutls_assert(); + ret = GNUTLS_E_INTERNAL_ERROR; + goto error; + + } + + /* Auth_info structures copied. Now copy security_parameters_st. + * packed_session must have allocated space for the security parameters. + */ + ret = unpack_security_parameters(session, &sb); + if (ret < 0) { + gnutls_assert(); + goto error; + } + + ret = _gnutls_ext_unpack(session, &sb); + if (ret < 0) { + gnutls_assert(); + goto error; + } + + ret = 0; + + error: + _gnutls_buffer_clear(&sb); + + return ret; +} + + + +/* Format: + * 1 byte the credentials type + * 4 bytes the size of the whole structure + * DH stuff + * 2 bytes the size of secret key in bits + * 4 bytes the size of the prime + * x bytes the prime + * 4 bytes the size of the generator + * x bytes the generator + * 4 bytes the size of the public key + * x bytes the public key + * RSA stuff + * 4 bytes the size of the modulus + * x bytes the modulus + * 4 bytes the size of the exponent + * x bytes the exponent + * CERTIFICATES + * 4 bytes the length of the certificate list + * 4 bytes the size of first certificate + * x bytes the certificate + * and so on... + */ +static int +pack_certificate_auth_info(gnutls_session_t session, gnutls_buffer_st * ps) +{ + unsigned int i; + int cur_size, ret; + cert_auth_info_t info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE); + int size_offset; + + size_offset = ps->length; + BUFFER_APPEND_NUM(ps, 0); + cur_size = ps->length; + + if (info) { + + BUFFER_APPEND_NUM(ps, info->dh.secret_bits); + BUFFER_APPEND_PFX4(ps, info->dh.prime.data, + info->dh.prime.size); + BUFFER_APPEND_PFX4(ps, info->dh.generator.data, + info->dh.generator.size); + BUFFER_APPEND_PFX4(ps, info->dh.public_key.data, + info->dh.public_key.size); + + BUFFER_APPEND_NUM(ps, info->ncerts); + + for (i = 0; i < info->ncerts; i++) + BUFFER_APPEND_PFX4(ps, + info->raw_certificate_list[i]. + data, + info->raw_certificate_list[i]. + size); + } + + /* write the real size */ + _gnutls_write_uint32(ps->length - cur_size, + ps->data + size_offset); + + return 0; +} + + +/* Upack certificate info. + */ +static int +unpack_certificate_auth_info(gnutls_session_t session, + gnutls_buffer_st * ps) +{ + int ret; + unsigned int i = 0, j = 0; + size_t pack_size; + cert_auth_info_t info = NULL; + + BUFFER_POP_NUM(ps, pack_size); + + if (pack_size == 0) + return 0; /* nothing to be done */ + + /* client and server have the same auth_info here + */ + ret = + _gnutls_auth_info_set(session, GNUTLS_CRD_CERTIFICATE, + sizeof(cert_auth_info_st), 1); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE); + if (info == NULL) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + + BUFFER_POP_NUM(ps, info->dh.secret_bits); + + BUFFER_POP_DATUM(ps, &info->dh.prime); + BUFFER_POP_DATUM(ps, &info->dh.generator); + BUFFER_POP_DATUM(ps, &info->dh.public_key); + + BUFFER_POP_NUM(ps, info->ncerts); + + if (info->ncerts > 0) { + info->raw_certificate_list = + gnutls_calloc(info->ncerts, sizeof(gnutls_datum_t)); + if (info->raw_certificate_list == NULL) { + gnutls_assert(); + ret = GNUTLS_E_MEMORY_ERROR; + goto error; + } + } + + for (i = 0; i < info->ncerts; i++) { + BUFFER_POP_DATUM(ps, &info->raw_certificate_list[i]); + } + + return 0; + + error: + if (info) { + _gnutls_free_datum(&info->dh.prime); + _gnutls_free_datum(&info->dh.generator); + _gnutls_free_datum(&info->dh.public_key); + + for (j = 0; j < i; j++) + _gnutls_free_datum(&info->raw_certificate_list[j]); + + gnutls_free(info->raw_certificate_list); + } + + return ret; + +} + +#ifdef ENABLE_SRP +/* Packs the SRP session authentication data. + */ + +/* Format: + * 1 byte the credentials type + * 4 bytes the size of the SRP username (x) + * x bytes the SRP username + */ +static int +pack_srp_auth_info(gnutls_session_t session, gnutls_buffer_st * ps) +{ + srp_server_auth_info_t info = _gnutls_get_auth_info(session, GNUTLS_CRD_SRP); + int len, ret; + int size_offset; + size_t cur_size; + const char *username = NULL; + + if (info && info->username) { + username = info->username; + len = strlen(info->username) + 1; /* include the terminating null */ + } else + len = 0; + + size_offset = ps->length; + BUFFER_APPEND_NUM(ps, 0); + cur_size = ps->length; + + BUFFER_APPEND_PFX4(ps, username, len); + + /* write the real size */ + _gnutls_write_uint32(ps->length - cur_size, + ps->data + size_offset); + + return 0; +} + + +static int +unpack_srp_auth_info(gnutls_session_t session, gnutls_buffer_st * ps) +{ + size_t username_size; + int ret; + srp_server_auth_info_t info; + + BUFFER_POP_NUM(ps, username_size); + if (username_size > sizeof(info->username)) { + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } + + ret = + _gnutls_auth_info_set(session, GNUTLS_CRD_SRP, + sizeof(srp_server_auth_info_st), 1); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + info = _gnutls_get_auth_info(session, GNUTLS_CRD_SRP); + if (info == NULL) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + + BUFFER_POP(ps, info->username, username_size); + if (username_size == 0) + info->username[0] = 0; + + ret = 0; + + error: + return ret; +} +#endif + + +#ifdef ENABLE_ANON +/* Packs the ANON session authentication data. + */ + +/* Format: + * 1 byte the credentials type + * 4 bytes the size of the whole structure + * 2 bytes the size of secret key in bits + * 4 bytes the size of the prime + * x bytes the prime + * 4 bytes the size of the generator + * x bytes the generator + * 4 bytes the size of the public key + * x bytes the public key + */ +static int +pack_anon_auth_info(gnutls_session_t session, gnutls_buffer_st * ps) +{ + int cur_size, ret; + anon_auth_info_t info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON); + int size_offset; + + size_offset = ps->length; + BUFFER_APPEND_NUM(ps, 0); + cur_size = ps->length; + + if (info) { + BUFFER_APPEND_NUM(ps, info->dh.secret_bits); + BUFFER_APPEND_PFX4(ps, info->dh.prime.data, + info->dh.prime.size); + BUFFER_APPEND_PFX4(ps, info->dh.generator.data, + info->dh.generator.size); + BUFFER_APPEND_PFX4(ps, info->dh.public_key.data, + info->dh.public_key.size); + } + + /* write the real size */ + _gnutls_write_uint32(ps->length - cur_size, + ps->data + size_offset); + + return 0; +} + + +static int +unpack_anon_auth_info(gnutls_session_t session, gnutls_buffer_st * ps) +{ + int ret; + size_t pack_size; + anon_auth_info_t info = NULL; + + BUFFER_POP_NUM(ps, pack_size); + + if (pack_size == 0) + return 0; /* nothing to be done */ + + /* client and server have the same auth_info here + */ + ret = + _gnutls_auth_info_set(session, GNUTLS_CRD_ANON, + sizeof(anon_auth_info_st), 1); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON); + if (info == NULL) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + + BUFFER_POP_NUM(ps, info->dh.secret_bits); + + BUFFER_POP_DATUM(ps, &info->dh.prime); + BUFFER_POP_DATUM(ps, &info->dh.generator); + BUFFER_POP_DATUM(ps, &info->dh.public_key); + + return 0; + + error: + if (info) { + _gnutls_free_datum(&info->dh.prime); + _gnutls_free_datum(&info->dh.generator); + _gnutls_free_datum(&info->dh.public_key); + } + + return ret; +} +#endif /* ANON */ + +#ifdef ENABLE_PSK +/* Packs the PSK session authentication data. + */ + +/* Format: + * 1 byte the credentials type + * 4 bytes the size of the whole structure + * + * 4 bytes the size of the PSK username (x) + * x bytes the PSK username + * 2 bytes the size of secret key in bits + * 4 bytes the size of the prime + * x bytes the prime + * 4 bytes the size of the generator + * x bytes the generator + * 4 bytes the size of the public key + * x bytes the public key + */ +static int +pack_psk_auth_info(gnutls_session_t session, gnutls_buffer_st * ps) +{ + psk_auth_info_t info; + int username_len; + int hint_len, ret; + int size_offset; + size_t cur_size; + + info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK); + if (info == NULL) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + + username_len = strlen(info->username) + 1; /* include the terminating null */ + hint_len = strlen(info->hint) + 1; /* include the terminating null */ + + size_offset = ps->length; + BUFFER_APPEND_NUM(ps, 0); + cur_size = ps->length; + + BUFFER_APPEND_PFX4(ps, info->username, username_len); + BUFFER_APPEND_PFX4(ps, info->hint, hint_len); + + BUFFER_APPEND_NUM(ps, info->dh.secret_bits); + BUFFER_APPEND_PFX4(ps, info->dh.prime.data, info->dh.prime.size); + BUFFER_APPEND_PFX4(ps, info->dh.generator.data, + info->dh.generator.size); + BUFFER_APPEND_PFX4(ps, info->dh.public_key.data, + info->dh.public_key.size); + + /* write the real size */ + _gnutls_write_uint32(ps->length - cur_size, + ps->data + size_offset); + return 0; +} + +static int +unpack_psk_auth_info(gnutls_session_t session, gnutls_buffer_st * ps) +{ + size_t username_size, hint_size; + int ret; + psk_auth_info_t info; + unsigned pack_size; + + ret = + _gnutls_auth_info_set(session, GNUTLS_CRD_PSK, + sizeof(psk_auth_info_st), 1); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK); + if (info == NULL) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + + BUFFER_POP_NUM(ps, pack_size); + if (pack_size == 0) + return GNUTLS_E_INVALID_REQUEST; + + BUFFER_POP_NUM(ps, username_size); + if (username_size > sizeof(info->username)) { + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } + + BUFFER_POP(ps, info->username, username_size); + + BUFFER_POP_NUM(ps, hint_size); + if (hint_size > sizeof(info->hint)) { + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } + BUFFER_POP(ps, info->hint, hint_size); + + BUFFER_POP_NUM(ps, info->dh.secret_bits); + + BUFFER_POP_DATUM(ps, &info->dh.prime); + BUFFER_POP_DATUM(ps, &info->dh.generator); + BUFFER_POP_DATUM(ps, &info->dh.public_key); + + ret = 0; + + error: + _gnutls_free_datum(&info->dh.prime); + _gnutls_free_datum(&info->dh.generator); + _gnutls_free_datum(&info->dh.public_key); + + return ret; +} +#endif + + +/* Packs the security parameters. + */ + +/* Format: + * 4 bytes the total security data size + * 1 byte the entity type (client/server) + * 1 byte the key exchange algorithm used + * 1 byte the read cipher algorithm + * 1 byte the read mac algorithm + * 1 byte the read compression algorithm + * + * 1 byte the write cipher algorithm + * 1 byte the write mac algorithm + * 1 byte the write compression algorithm + * + * 1 byte the certificate type + * 1 byte the protocol version + * + * 2 bytes the cipher suite + * + * 48 bytes the master secret + * + * 32 bytes the client random + * 32 bytes the server random + * + * 1 byte the session ID size + * x bytes the session ID (32 bytes max) + * + * 4 bytes the new record padding flag + * 4 bytes the ECC curve + * ------------------- + * MAX: 169 bytes + * + */ +static int +pack_security_parameters(gnutls_session_t session, gnutls_buffer_st * ps) +{ + + int ret; + int size_offset; + size_t cur_size; + record_parameters_st *params; + + if (session->security_parameters.epoch_read + != session->security_parameters.epoch_write) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + ret = _gnutls_epoch_get(session, EPOCH_READ_CURRENT, ¶ms); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + /* move after the auth info stuff. + */ + size_offset = ps->length; + BUFFER_APPEND_NUM(ps, 0); + cur_size = ps->length; + + + BUFFER_APPEND_NUM(ps, session->security_parameters.entity); + BUFFER_APPEND_NUM(ps, session->security_parameters.kx_algorithm); + BUFFER_APPEND(ps, session->security_parameters.cipher_suite, 2); + BUFFER_APPEND_NUM(ps, + session->security_parameters.compression_method); + BUFFER_APPEND_NUM(ps, session->security_parameters.cert_type); + BUFFER_APPEND_NUM(ps, session->security_parameters.pversion->id); + + BUFFER_APPEND(ps, session->security_parameters.master_secret, + GNUTLS_MASTER_SIZE); + BUFFER_APPEND(ps, session->security_parameters.client_random, + GNUTLS_RANDOM_SIZE); + BUFFER_APPEND(ps, session->security_parameters.server_random, + GNUTLS_RANDOM_SIZE); + + BUFFER_APPEND(ps, &session->security_parameters.session_id_size, + 1); + BUFFER_APPEND(ps, session->security_parameters.session_id, + session->security_parameters.session_id_size); + + BUFFER_APPEND_NUM(ps, + session->security_parameters. + max_record_send_size); + BUFFER_APPEND_NUM(ps, + session->security_parameters. + max_record_recv_size); + BUFFER_APPEND_NUM(ps, session->security_parameters.ecc_curve); + + BUFFER_APPEND_NUM(ps, + session->security_parameters.server_sign_algo); + BUFFER_APPEND_NUM(ps, + session->security_parameters.client_sign_algo); + BUFFER_APPEND_NUM(ps, + session->security_parameters.ext_master_secret); + BUFFER_APPEND_NUM(ps, + session->security_parameters.etm); + + _gnutls_write_uint32(ps->length - cur_size, + ps->data + size_offset); + + return 0; +} + +static int +unpack_security_parameters(gnutls_session_t session, gnutls_buffer_st * ps) +{ + size_t pack_size; + int ret; + unsigned version; + time_t timestamp; + + BUFFER_POP_NUM(ps, pack_size); + + if (pack_size == 0) + return GNUTLS_E_INVALID_REQUEST; + + timestamp = + session->internals.resumed_security_parameters.timestamp; + memset(&session->internals.resumed_security_parameters, 0, + sizeof(session->internals.resumed_security_parameters)); + session->internals.resumed_security_parameters.timestamp = + timestamp; + + timestamp = gnutls_time(0); + + BUFFER_POP_NUM(ps, + session->internals.resumed_security_parameters. + entity); + BUFFER_POP_NUM(ps, + session->internals.resumed_security_parameters. + kx_algorithm); + BUFFER_POP(ps, + session->internals.resumed_security_parameters. + cipher_suite, 2); + BUFFER_POP_NUM(ps, + session->internals.resumed_security_parameters. + compression_method); + BUFFER_POP_NUM(ps, + session->internals.resumed_security_parameters. + cert_type); + BUFFER_POP_NUM(ps, version); + session->internals.resumed_security_parameters.pversion = + version_to_entry(version); + if (session->internals.resumed_security_parameters.pversion == + NULL) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + BUFFER_POP(ps, + session->internals.resumed_security_parameters. + master_secret, GNUTLS_MASTER_SIZE); + + BUFFER_POP(ps, + session->internals.resumed_security_parameters. + client_random, GNUTLS_RANDOM_SIZE); + BUFFER_POP(ps, + session->internals.resumed_security_parameters. + server_random, GNUTLS_RANDOM_SIZE); + BUFFER_POP(ps, + &session->internals.resumed_security_parameters. + session_id_size, 1); + + BUFFER_POP(ps, + session->internals.resumed_security_parameters. + session_id, + session->internals.resumed_security_parameters. + session_id_size); + + BUFFER_POP_NUM(ps, + session->internals.resumed_security_parameters. + max_record_send_size); + BUFFER_POP_NUM(ps, + session->internals.resumed_security_parameters. + max_record_recv_size); + + BUFFER_POP_NUM(ps, + session->internals.resumed_security_parameters. + ecc_curve); + BUFFER_POP_NUM(ps, + session->internals.resumed_security_parameters. + server_sign_algo); + BUFFER_POP_NUM(ps, + session->internals.resumed_security_parameters. + client_sign_algo); + BUFFER_POP_NUM(ps, + session->internals.resumed_security_parameters. + ext_master_secret); + BUFFER_POP_NUM(ps, + session->internals.resumed_security_parameters. + etm); + + if (session->internals.resumed_security_parameters. + max_record_recv_size == 0 + || session->internals.resumed_security_parameters. + max_record_send_size == 0) { + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + } + + if (timestamp - + session->internals.resumed_security_parameters.timestamp > + session->internals.expire_time + || session->internals.resumed_security_parameters.timestamp > + timestamp) { + gnutls_assert(); + return GNUTLS_E_EXPIRED; + } + + ret = 0; + + error: + return ret; +} + +/** + * gnutls_session_set_premaster: + * @session: is a #gnutls_session_t type. + * @entity: GNUTLS_SERVER or GNUTLS_CLIENT + * @version: the TLS protocol version + * @kx: the key exchange method + * @cipher: the cipher + * @mac: the MAC algorithm + * @comp: the compression method + * @master: the master key to use + * @session_id: the session identifier + * + * This function sets the premaster secret in a session. This is + * a function intended for exceptional uses. Do not use this + * function unless you are implementing a legacy protocol. + * Use gnutls_session_set_data() instead. + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise + * an error code is returned. + **/ +int +gnutls_session_set_premaster(gnutls_session_t session, unsigned int entity, + gnutls_protocol_t version, + gnutls_kx_algorithm_t kx, + gnutls_cipher_algorithm_t cipher, + gnutls_mac_algorithm_t mac, + gnutls_compression_method_t comp, + const gnutls_datum_t * master, + const gnutls_datum_t * session_id) +{ + int ret; + + memset(&session->internals.resumed_security_parameters, 0, + sizeof(session->internals.resumed_security_parameters)); + + session->internals.resumed_security_parameters.entity = entity; + session->internals.resumed_security_parameters.kx_algorithm = kx; + + ret = + _gnutls_cipher_suite_get_id(kx, cipher, mac, + session->internals. + resumed_security_parameters. + cipher_suite); + if (ret < 0) + return gnutls_assert_val(ret); + + session->internals.resumed_security_parameters.compression_method = + comp; + session->internals.resumed_security_parameters.cert_type = + DEFAULT_CERT_TYPE; + session->internals.resumed_security_parameters.pversion = + version_to_entry(version); + + if (session->internals.resumed_security_parameters.pversion == + NULL) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + if (master->size != GNUTLS_MASTER_SIZE) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + memcpy(session->internals.resumed_security_parameters. + master_secret, master->data, master->size); + + if (session_id->size > GNUTLS_MAX_SESSION_ID) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + session->internals.resumed_security_parameters.session_id_size = + session_id->size; + memcpy(session->internals.resumed_security_parameters.session_id, + session_id->data, session_id->size); + + session->internals.resumed_security_parameters. + max_record_send_size = + session->internals.resumed_security_parameters. + max_record_recv_size = DEFAULT_MAX_RECORD_SIZE; + + session->internals.resumed_security_parameters.timestamp = + gnutls_time(0); + + session->internals.resumed_security_parameters.ecc_curve = + GNUTLS_ECC_CURVE_INVALID; + + session->internals.premaster_set = 1; + + return 0; +} |