/*
* 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
*
*/
/* 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
#endif
#ifdef ENABLE_PSK
#include
#endif
#include
#include
#include "errors.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
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_assert_val(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) {
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);
if (username_size == 0)
info->username[0] = 0;
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);
if (hint_size == 0)
info->hint[0] = 0;
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_UNAVAILABLE_DURING_HANDSHAKE;
}
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;
}