Пример #1
0
/* Initializes the write connection session
 * (write encrypted data)
 */
int _gnutls_write_connection_state_init(gnutls_session_t session)
{
	const uint16_t epoch_next =
	    session->security_parameters.epoch_next;
	int ret;

/* Update internals from CipherSuite selected.
 * If we are resuming just copy the connection session
 */
	if (session->internals.resumed == RESUME_FALSE) {
		ret = _gnutls_set_kx(session,
				     _gnutls_cipher_suite_get_kx_algo
				     (session->security_parameters.
				      cipher_suite));
		if (ret < 0)
			return ret;
	} else if (session->security_parameters.entity == GNUTLS_SERVER)
		_gnutls_set_resumed_parameters(session);

	ret = _gnutls_epoch_set_keys(session, epoch_next);
	if (ret < 0)
		return gnutls_assert_val(ret);

	_gnutls_handshake_log("HSK[%p]: Cipher Suite: %s\n", session,
			      _gnutls_cipher_suite_get_name
			      (session->security_parameters.cipher_suite));

	_gnutls_handshake_log
	    ("HSK[%p]: Initializing internal [write] cipher sessions\n",
	     session);

	session->security_parameters.epoch_write = epoch_next;

	return 0;
}
Пример #2
0
static int parse_cert_extension(void *_ctx, unsigned tls_id, const uint8_t *data, unsigned data_size)
{
	crt_cert_ctx_st *ctx = _ctx;
	gnutls_session_t session = ctx->session;
	int ret;

	if (tls_id == STATUS_REQUEST_TLS_ID) {
#ifdef ENABLE_OCSP
		if (!_gnutls_hello_ext_is_present(session, ext_mod_status_request.gid)) {
			gnutls_assert();
			goto unexpected;
		}

		_gnutls_handshake_log("Found OCSP response on cert %d\n", ctx->idx);

		ret = _gnutls_parse_ocsp_response(session, data, data_size, ctx->ocsp);
		if (ret < 0)
			return gnutls_assert_val(ret);
#endif
	} else {
		goto unexpected;
	}

	return 0;

 unexpected:
	_gnutls_debug_log("received unexpected certificate extension (%d)\n", (int)tls_id);
	return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION);
}
Пример #3
0
void
_gnutls_session_ecc_curve_set (gnutls_session_t session,
                               gnutls_ecc_curve_t c)
{
  _gnutls_handshake_log("HSK[%p]: Selected ECC curve %s (%d)\n", session, gnutls_ecc_curve_get_name(c), c);
  session->security_parameters.ecc_curve = c;
}
Пример #4
0
void
_gnutls_session_cert_type_set (gnutls_session_t session,
                               gnutls_certificate_type_t ct)
{
  _gnutls_handshake_log("HSK[%p]: Selected certificate type %s (%d)\n", session,
        gnutls_certificate_type_get_name(ct), ct);
  session->security_parameters.cert_type = ct;
}
Пример #5
0
int _gnutls13_recv_session_ticket(gnutls_session_t session, gnutls_buffer_st *buf)
{
	int ret;
	uint8_t value;
	tls13_ticket_st *ticket = &session->internals.tls13_ticket;
	gnutls_datum_t t;
	size_t val;

	if (unlikely(buf == NULL))
		return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);

	_gnutls_free_datum(&ticket->ticket);
	memset(ticket, 0, sizeof(tls13_ticket_st));

	_gnutls_handshake_log("HSK[%p]: parsing session ticket message\n", session);

	/* ticket_lifetime */
	ret = _gnutls_buffer_pop_prefix32(buf, &val, 0);
	if (ret < 0)
		return gnutls_assert_val(ret);
	ticket->lifetime = val;

	/* ticket_age_add */
	ret = _gnutls_buffer_pop_prefix32(buf, &val, 0);
	if (ret < 0)
		return gnutls_assert_val(ret);
	ticket->age_add = val;

	/* ticket_nonce */
	ret = _gnutls_buffer_pop_prefix8(buf, &value, 0);
	if (ret < 0)
		return gnutls_assert_val(ret);

	ticket->nonce_size = value;
	ret = _gnutls_buffer_pop_data(buf, ticket->nonce, ticket->nonce_size);
	if (ret < 0)
		return gnutls_assert_val(ret);

	/* ticket */
	ret = _gnutls_buffer_pop_datum_prefix16(buf, &t);
	if (ret < 0)
		return gnutls_assert_val(ret);

	gnutls_free(ticket->ticket.data);
	ret = _gnutls_set_datum(&ticket->ticket, t.data, t.size);
	if (ret < 0)
		return gnutls_assert_val(ret);

	/* Extensions */
	ret = _gnutls_extv_parse(session, parse_nst_extension, buf->data, buf->length);
	if (ret < 0)
		return gnutls_assert_val(ret);

	/* Record the ticket arrival time */
	gnutls_gettime(&ticket->arrival_time);

	return 0;
}
Пример #6
0
/* Adds the extension we want to send in the extensions list.
 * This list is used to check whether the (later) received
 * extensions are the ones we requested.
 */
void _gnutls_extension_list_add(gnutls_session_t session, uint16_t type)
{

	if (session->internals.extensions_sent_size <
	    MAX_EXT_TYPES) {
		session->internals.extensions_sent[session->
						   internals.extensions_sent_size]
		    = type;
		session->internals.extensions_sent_size++;
	} else {
		_gnutls_handshake_log
		    ("extensions: Increase MAX_EXT_TYPES\n");
	}
}
Пример #7
0
/* This function is to be called if the handshake was successfully 
 * completed. This sends a Change Cipher Spec packet to the peer.
 */
ssize_t
_gnutls_send_change_cipher_spec (gnutls_session_t session, int again)
{
  static const opaque data[1] = { GNUTLS_TYPE_CHANGE_CIPHER_SPEC };

  _gnutls_handshake_log ("REC[%x]: Sent ChangeCipherSpec\n", session);

  if (again == 0)
    return _gnutls_send_int (session, GNUTLS_CHANGE_CIPHER_SPEC, -1, data, 1);
  else
    {
      return _gnutls_io_write_flush (session);
    }
}
Пример #8
0
/* Adds the extension we want to send in the extensions list.
 * This list is used to check whether the (later) received
 * extensions are the ones we requested.
 */
void _gnutls_extension_list_add(gnutls_session_t session, uint16_t type)
{

	if (session->security_parameters.entity == GNUTLS_CLIENT) {
		if (session->internals.extensions_sent_size <
		    MAX_EXT_TYPES) {
			session->internals.extensions_sent[session->
							   internals.extensions_sent_size]
			    = type;
			session->internals.extensions_sent_size++;
		} else {
			_gnutls_handshake_log
			    ("extensions: Increase MAX_EXT_TYPES\n");
		}
	}
}
Пример #9
0
/* Parses the Signature Algorithm structure and stores data into
 * session->security_parameters.extensions.
 */
int
_gnutls_sign_algorithm_parse_data(gnutls_session_t session,
				  const uint8_t * data, size_t data_size)
{
	unsigned int sig, i;
	sig_ext_st *priv;
	extension_priv_data_t epriv;

	if (data_size % 2 != 0)
		return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);

	priv = gnutls_calloc(1, sizeof(*priv));
	if (priv == NULL) {
		gnutls_assert();
		return GNUTLS_E_MEMORY_ERROR;
	}

	for (i = 0; i < data_size; i += 2) {
		sign_algorithm_st aid;

		aid.hash_algorithm = data[i];
		aid.sign_algorithm = data[i + 1];

		sig = _gnutls_tls_aid_to_sign(&aid);

		_gnutls_handshake_log
		    ("EXT[%p]: rcvd signature algo (%d.%d) %s\n", session,
		     aid.hash_algorithm, aid.sign_algorithm,
		     gnutls_sign_get_name(sig));

		if (sig != GNUTLS_SIGN_UNKNOWN) {
			priv->sign_algorithms[priv->
					      sign_algorithms_size++] =
			    sig;
			if (priv->sign_algorithms_size ==
			    MAX_SIGNATURE_ALGORITHMS)
				break;
		}
	}

	epriv = priv;
	_gnutls_ext_set_session_data(session,
				     GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
				     epriv);

	return 0;
}
Пример #10
0
/* generates a SignatureAndHashAlgorithm structure with length as prefix
 * by using the setup priorities.
 */
int
_gnutls_sign_algorithm_write_params(gnutls_session_t session,
				    uint8_t * data, size_t max_data_size)
{
	uint8_t *p = data, *len_p;
	unsigned int len, i, j;
	const sign_algorithm_st *aid;

	if (max_data_size <
	    (session->internals.priorities.sign_algo.algorithms * 2) + 2) {
		gnutls_assert();
		return GNUTLS_E_SHORT_MEMORY_BUFFER;
	}

	len = 0;
	len_p = p;

	p += 2;

	for (i = j = 0;
	     j < session->internals.priorities.sign_algo.algorithms;
	     i += 2, j++) {
		aid =
		    _gnutls_sign_to_tls_aid(session->internals.
					    priorities.sign_algo.
					    priority[j]);

		if (aid == NULL)
			continue;

		_gnutls_handshake_log
		    ("EXT[%p]: sent signature algo (%d.%d) %s\n", session,
		     aid->hash_algorithm, aid->sign_algorithm,
		     gnutls_sign_get_name(session->internals.priorities.
					  sign_algo.priority[j]));
		*p = aid->hash_algorithm;
		p++;
		*p = aid->sign_algorithm;
		p++;
		len += 2;
	}

	_gnutls_write_uint16(len, len_p);
	return len + 2;
}
Пример #11
0
/* Initializes the read connection session
 * (read encrypted data)
 */
int
_gnutls_read_connection_state_init (gnutls_session_t session)
{
  const uint16_t epoch_next = session->security_parameters.epoch_next;
  int ret;

  /* Update internals from CipherSuite selected.
   * If we are resuming just copy the connection session
   */
  if (session->internals.resumed == RESUME_FALSE)
    {

      ret = _gnutls_check_algos (session,
                                 &session->
                                 security_parameters.current_cipher_suite,
                                 _gnutls_epoch_get_compression(session, epoch_next));
      if (ret < 0)
        return ret;

      ret = _gnutls_set_kx (session,
                            _gnutls_cipher_suite_get_kx_algo
                            (&session->
                             security_parameters.current_cipher_suite));
      if (ret < 0)
        return ret;
    }
  else if (session->security_parameters.entity == GNUTLS_CLIENT)
    _gnutls_set_resumed_parameters (session);

  ret = _gnutls_epoch_set_keys (session, epoch_next);
  if (ret < 0)
    return ret;

  _gnutls_handshake_log ("HSK[%p]: Cipher Suite: %s\n",
                         session,
                         _gnutls_cipher_suite_get_name
                         (&session->
                          security_parameters.current_cipher_suite));

  session->security_parameters.epoch_read = epoch_next;

  return 0;
}
Пример #12
0
/* This selects the best supported ciphersuite from the ones provided */
static int
_gnutls_handshake_select_v2_suite (gnutls_session_t session,
				   opaque * data, int datalen)
{
  int i, j, ret;
  opaque *_data;
  int _datalen;

  _gnutls_handshake_log ("HSK[%x]: Parsing a version 2.0 client hello.\n",
			 session);

  _data = gnutls_malloc (datalen);
  if (_data == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  if (datalen % 3 != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
    }

  i = _datalen = 0;
  for (j = 0; j < datalen; j += 3)
    {
      if (data[j] == 0)
	{
	  memcpy (&_data[i], &data[j + 1], 2);
	  i += 2;
	  _datalen += 2;
	}
    }

  ret = _gnutls_server_select_suite (session, _data, _datalen);
  gnutls_free (_data);

  return ret;

}
Пример #13
0
int _gnutls13_send_key_update(gnutls_session_t session, unsigned again, unsigned flags /* GNUTLS_KU_* */)
{
	int ret;
	mbuffer_st *bufel = NULL;
	uint8_t val;

	if (again == 0) {
		if (flags & GNUTLS_KU_PEER) {
			/* mark that we asked a key update to prevent an
			 * infinite ping pong when receiving the reply */
			session->internals.hsk_flags |= HSK_KEY_UPDATE_ASKED;
			val = 0x01;
		} else {
			val = 0x00;
		}

		_gnutls_handshake_log("HSK[%p]: sending key update (%u)\n", session, (unsigned)val);

		bufel = _gnutls_handshake_alloc(session, 1);
		if (bufel == NULL)
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

		_mbuffer_set_udata_size(bufel, 0);
		ret = _mbuffer_append_data(bufel, &val, 1);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

	}

	return _gnutls_send_handshake(session, bufel, GNUTLS_HANDSHAKE_KEY_UPDATE);

cleanup:
	_mbuffer_xfree(&bufel);
	return ret;
}
Пример #14
0
static int
server_recv(gnutls_session_t session,
	    status_request_ext_st * priv,
	    const uint8_t * data, size_t size)
{
	size_t i;
	ssize_t data_size = size;

	/* minimum message is type (1) + responder_id_list (2) +
	   request_extension (2) = 5 */
	if (data_size < 5)
		return
		    gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);

	/* We ignore non-ocsp CertificateStatusType.  The spec is unclear
	   what should be done. */
	if (data[0] != 0x01) {
		gnutls_assert();
		_gnutls_handshake_log("EXT[%p]: unknown status_type %d\n",
				      session, data[0]);
		return 0;
	}
	DECR_LEN(data_size, 1);
	data++;

	priv->responder_id_size = _gnutls_read_uint16(data);

	DECR_LEN(data_size, 2);
	data += 2;

	if (data_size <= (ssize_t) (priv->responder_id_size * 2))
		return
		    gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);

	priv->responder_id = gnutls_malloc(priv->responder_id_size
					   * sizeof(*priv->responder_id));
	if (priv->responder_id == NULL)
		return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

	for (i = 0; i < priv->responder_id_size; i++) {
		size_t l;

		DECR_LEN(data_size, 2);

		l = _gnutls_read_uint16(data);
		data += 2;

		DECR_LEN(data_size, l);

		priv->responder_id[i].data = gnutls_malloc(l);
		if (priv->responder_id[i].data == NULL)
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

		memcpy(priv->responder_id[i].data, data, l);
		priv->responder_id[i].size = l;

		data += l;
	}

	return 0;
}
Пример #15
0
/* Read a v2 client hello. Some browsers still use that beast!
 * However they set their version to 3.0 or 3.1.
 */
int
_gnutls_read_client_hello_v2(gnutls_session_t session, uint8_t * data,
			     unsigned int datalen)
{
	uint16_t session_id_len = 0;
	int pos = 0;
	int ret = 0, sret = 0;
	uint16_t sizeOfSuites;
	gnutls_protocol_t adv_version;
	uint8_t rnd[GNUTLS_RANDOM_SIZE];
	int len = datalen;
	uint16_t challenge;
	uint8_t session_id[GNUTLS_MAX_SESSION_ID_SIZE];

	DECR_LEN(len, 2);

	_gnutls_handshake_log
	    ("HSK[%p]: SSL 2.0 Hello: Client's version: %d.%d\n", session,
	     data[pos], data[pos + 1]);

	set_adv_version(session, data[pos], data[pos + 1]);

	adv_version = _gnutls_version_get(data[pos], data[pos + 1]);

	ret = _gnutls_negotiate_version(session, adv_version);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	pos += 2;

	/* Read uint16_t cipher_spec_length */
	DECR_LEN(len, 2);
	sizeOfSuites = _gnutls_read_uint16(&data[pos]);
	pos += 2;

	/* read session id length */
	DECR_LEN(len, 2);
	session_id_len = _gnutls_read_uint16(&data[pos]);
	pos += 2;

	if (session_id_len > GNUTLS_MAX_SESSION_ID_SIZE) {
		gnutls_assert();
		return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
	}

	/* read challenge length */
	DECR_LEN(len, 2);
	challenge = _gnutls_read_uint16(&data[pos]);
	pos += 2;

	if (challenge < 16 || challenge > GNUTLS_RANDOM_SIZE) {
		gnutls_assert();
		return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
	}

	/* call the user hello callback
	 */
	ret = _gnutls_user_hello_func(session, adv_version);
	if (ret < 0) {
		if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) {
			sret = GNUTLS_E_INT_RET_0;
		} else {
			gnutls_assert();
			return ret;
		}
	}

	/* find an appropriate cipher suite */

	DECR_LEN(len, sizeOfSuites);
	ret =
	    _gnutls_handshake_select_v2_suite(session, &data[pos],
					      sizeOfSuites);

	pos += sizeOfSuites;
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	/* check if the credentials (username, public key etc.) are ok
	 */
	if (_gnutls_get_kx_cred
	    (session,
	     _gnutls_cipher_suite_get_kx_algo(session->security_parameters.
					      cipher_suite)) == NULL) {
		gnutls_assert();
		return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
	}

	/* set the mod_auth_st to the appropriate struct
	 * according to the KX algorithm. This is needed since all the
	 * handshake functions are read from there;
	 */
	session->internals.auth_struct =
	    _gnutls_kx_auth_struct(_gnutls_cipher_suite_get_kx_algo
				   (session->security_parameters.
				    cipher_suite));
	if (session->internals.auth_struct == NULL) {

		_gnutls_handshake_log
		    ("HSK[%p]: SSL 2.0 Hello: Cannot find the appropriate handler for the KX algorithm\n",
		     session);

		gnutls_assert();
		return GNUTLS_E_INTERNAL_ERROR;
	}

	/* read random new values -skip session id for now */
	DECR_LEN(len, session_id_len);	/* skip session id for now */
	memcpy(session_id, &data[pos], session_id_len);
	pos += session_id_len;

	DECR_LEN(len, challenge);
	memset(rnd, 0, GNUTLS_RANDOM_SIZE);

	memcpy(&rnd[GNUTLS_RANDOM_SIZE - challenge], &data[pos],
	       challenge);

	ret = _gnutls_set_client_random(session, rnd);
	if (ret < 0)
		return gnutls_assert_val(ret);

	/* generate server random value */
	ret = _gnutls_set_server_random(session, NULL);
	if (ret < 0)
		return gnutls_assert_val(ret);

	session->security_parameters.timestamp = gnutls_time(NULL);


	/* RESUME SESSION */

	DECR_LEN(len, session_id_len);
	ret =
	    _gnutls_server_restore_session(session, session_id,
					   session_id_len);

	if (ret == 0) {		/* resumed! */
		/* get the new random values */
		memcpy(session->internals.resumed_security_parameters.
		       server_random,
		       session->security_parameters.server_random,
		       GNUTLS_RANDOM_SIZE);
		memcpy(session->internals.resumed_security_parameters.
		       client_random,
		       session->security_parameters.client_random,
		       GNUTLS_RANDOM_SIZE);

		session->internals.resumed = RESUME_TRUE;
		return 0;
	} else {
		_gnutls_generate_session_id(session->security_parameters.
					    session_id,
					    &session->security_parameters.
					    session_id_size);
		session->internals.resumed = RESUME_FALSE;
	}

	_gnutls_epoch_set_compression(session, EPOCH_NEXT,
				      GNUTLS_COMP_NULL);
	session->security_parameters.compression_method = GNUTLS_COMP_NULL;

	return sret;
}
Пример #16
0
int _gnutls13_recv_key_update(gnutls_session_t session, gnutls_buffer_st *buf)
{
	int ret;
	time_t now = gnutls_time(0);

	if (buf->length != 1)
		return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);

	if (unlikely(now - session->internals.last_key_update < KEY_UPDATES_PER_SEC)) {
		_gnutls_debug_log("reached maximum number of key updates per second (%d)\n",
				  KEY_UPDATES_PER_SEC);
		return gnutls_assert_val(GNUTLS_E_TOO_MANY_HANDSHAKE_PACKETS);
	}

	session->internals.last_key_update = now;

	_gnutls_epoch_gc(session);

	_gnutls_handshake_log("HSK[%p]: received TLS 1.3 key update (%u)\n",
			      session, (unsigned)buf->data[0]);

	switch(buf->data[0]) {
	case 0:
		/* peer updated its key, not requested our key update */
		ret = update_keys(session, STAGE_UPD_PEERS);
		if (ret < 0)
			return gnutls_assert_val(ret);

		break;
	case 1:
		if (session->internals.hsk_flags & HSK_KEY_UPDATE_ASKED) {
			/* if we had asked a key update we shouldn't get this
			 * reply */
			return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
		}

		/* peer updated its key, requested our key update */
		ret = update_keys(session, STAGE_UPD_PEERS);
		if (ret < 0)
			return gnutls_assert_val(ret);

		/* we mark that a key update is schedule, and it
		 * will be performed prior to sending the next application
		 * message.
		 */
		if (session->internals.rsend_state == RECORD_SEND_NORMAL)
			session->internals.rsend_state = RECORD_SEND_KEY_UPDATE_1;
		else if (session->internals.rsend_state == RECORD_SEND_CORKED)
			session->internals.rsend_state = RECORD_SEND_CORKED_TO_KU;
		else
			return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);

		break;
	default:
		return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
	}

	session->internals.hsk_flags &= ~(unsigned)(HSK_KEY_UPDATE_ASKED);

	return 0;
}
Пример #17
0
static int
parse_handshake_header(gnutls_session_t session, mbuffer_st * bufel,
		       handshake_buffer_st * hsk)
{
	uint8_t *dataptr = NULL;	/* for realloc */
	size_t handshake_header_size =
	    HANDSHAKE_HEADER_SIZE(session), data_size;

	/* Note: SSL2_HEADERS == 1 */
	if (_mbuffer_get_udata_size(bufel) < handshake_header_size)
		return
		    gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);

	dataptr = _mbuffer_get_udata_ptr(bufel);

	/* if reading a client hello of SSLv2 */
#ifdef ENABLE_SSL2
	if (unlikely
	    (!IS_DTLS(session)
	     && bufel->htype == GNUTLS_HANDSHAKE_CLIENT_HELLO_V2)) {
		handshake_header_size = SSL2_HEADERS;	/* we've already read one byte */

		hsk->length = _mbuffer_get_udata_size(bufel) - handshake_header_size;	/* we've read the first byte */

		if (dataptr[0] != GNUTLS_HANDSHAKE_CLIENT_HELLO)
			return
			    gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);

		hsk->htype = GNUTLS_HANDSHAKE_CLIENT_HELLO_V2;

		hsk->sequence = 0;
		hsk->start_offset = 0;
		hsk->end_offset = hsk->length;
	} else
#endif
	{		/* TLS or DTLS handshake headers */


		hsk->htype = dataptr[0];

		/* we do not use DECR_LEN because we know
		 * that the packet has enough data.
		 */
		hsk->length = _gnutls_read_uint24(&dataptr[1]);
		handshake_header_size = HANDSHAKE_HEADER_SIZE(session);

		if (IS_DTLS(session)) {
			hsk->sequence = _gnutls_read_uint16(&dataptr[4]);
			hsk->start_offset =
			    _gnutls_read_uint24(&dataptr[6]);
			hsk->end_offset =
			    hsk->start_offset +
			    _gnutls_read_uint24(&dataptr[9]);
		} else {
			hsk->sequence = 0;
			hsk->start_offset = 0;
			hsk->end_offset =
			    MIN((_mbuffer_get_udata_size(bufel) -
				 handshake_header_size), hsk->length);
		}
	}
	data_size = _mbuffer_get_udata_size(bufel) - handshake_header_size;

	/* make the length offset */
	if (hsk->end_offset > 0)
		hsk->end_offset--;

	_gnutls_handshake_log
	    ("HSK[%p]: %s (%u) was received. Length %d[%d], frag offset %d, frag length: %d, sequence: %d\n",
	     session, _gnutls_handshake2str(hsk->htype),
	     (unsigned) hsk->htype, (int) hsk->length, (int) data_size,
	     hsk->start_offset, hsk->end_offset - hsk->start_offset + 1,
	     (int) hsk->sequence);

	hsk->header_size = handshake_header_size;
	memcpy(hsk->header, _mbuffer_get_udata_ptr(bufel),
	       handshake_header_size);

	if (hsk->length > 0 &&
	    (hsk->end_offset - hsk->start_offset >= data_size))
		return
		    gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);

	if (hsk->length > 0 && (hsk->start_offset >= hsk->end_offset ||
				hsk->end_offset - hsk->start_offset >=
				data_size
				|| hsk->end_offset >= hsk->length))
		return
		    gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
	else if (hsk->length == 0 && hsk->end_offset != 0
		 && hsk->start_offset != 0)
		return
		    gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);

	return handshake_header_size;
}
Пример #18
0
static int
client_send_params(gnutls_session_t session,
		   gnutls_buffer_t extdata,
		   const gnutls_psk_client_credentials_t cred)
{
	int ret, ext_offset = 0;
	uint8_t binder_value[MAX_HASH_SIZE];
	size_t spos;
	gnutls_datum_t username = {NULL, 0};
	gnutls_datum_t user_key = {NULL, 0}, rkey = {NULL, 0};
	gnutls_datum_t client_hello;
	unsigned next_idx;
	const mac_entry_st *prf_res = NULL;
	const mac_entry_st *prf_psk = NULL;
	struct timespec cur_time;
	uint32_t ticket_age, ob_ticket_age;
	int free_username = 0;
	psk_auth_info_t info = NULL;
	unsigned psk_id_len = 0;
	unsigned binders_len, binders_pos;

	if (((session->internals.flags & GNUTLS_NO_TICKETS) ||
	    session->internals.tls13_ticket.ticket.data == NULL) &&
	    (!cred || !_gnutls_have_psk_credentials(cred, session))) {

		return 0;
	}

	binders_len = 0;

	/* placeholder to be filled later */
	spos = extdata->length;
	ret = _gnutls_buffer_append_prefix(extdata, 16, 0);
	if (ret < 0)
		return gnutls_assert_val(ret);

	/* First, let's see if we have a session ticket to send */
	if (!(session->internals.flags & GNUTLS_NO_TICKETS) &&
	    session->internals.tls13_ticket.ticket.data != NULL) {
		/* We found a session ticket */
		if (unlikely(session->internals.tls13_ticket.prf == NULL)) {
			_gnutls13_session_ticket_unset(session);
			ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
			goto cleanup;
		}

		prf_res = session->internals.tls13_ticket.prf;

		gnutls_gettime(&cur_time);
		if (unlikely(_gnutls_timespec_cmp(&cur_time,
						  &session->internals.
						  tls13_ticket.
						  arrival_time) < 0)) {
			gnutls_assert();
			_gnutls13_session_ticket_unset(session);
			goto ignore_ticket;
		}

		/* Check whether the ticket is stale */
		ticket_age = timespec_sub_ms(&cur_time,
					     &session->internals.tls13_ticket.
					     arrival_time);
		if (ticket_age / 1000 > session->internals.tls13_ticket.lifetime) {
			_gnutls13_session_ticket_unset(session);
			goto ignore_ticket;
		}

		ret = compute_psk_from_ticket(&session->internals.tls13_ticket, &rkey);
		if (ret < 0) {
			_gnutls13_session_ticket_unset(session);
			goto ignore_ticket;
		}

		/* Calculate obfuscated ticket age, in milliseconds, mod 2^32 */
		ob_ticket_age = ticket_age + session->internals.tls13_ticket.age_add;

		if ((ret = _gnutls_buffer_append_data_prefix(extdata, 16,
							     session->internals.tls13_ticket.ticket.data,
							     session->internals.tls13_ticket.ticket.size)) < 0) {
			gnutls_assert();
			goto cleanup;
		}

		/* Now append the obfuscated ticket age */
		if ((ret = _gnutls_buffer_append_prefix(extdata, 32, ob_ticket_age)) < 0) {
			gnutls_assert();
			goto cleanup;
		}

		psk_id_len += 6 + session->internals.tls13_ticket.ticket.size;
		binders_len += 1 + _gnutls_mac_get_algo_len(prf_res);
	}

 ignore_ticket:
	if (cred && _gnutls_have_psk_credentials(cred, session)) {
		gnutls_datum_t tkey;

		if (cred->binder_algo == NULL) {
			gnutls_assert();
			ret = gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
			goto cleanup;
		}

		prf_psk = cred->binder_algo;

		ret = _gnutls_find_psk_key(session, cred, &username, &tkey, &free_username);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		if (username.size == 0 || username.size > UINT16_MAX) {
			ret = gnutls_assert_val(GNUTLS_E_INVALID_PASSWORD);
			goto cleanup;
		}

		if (!free_username) {
			/* we need to copy the key */
			ret = _gnutls_set_datum(&user_key, tkey.data, tkey.size);
			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}
		} else {
			user_key.data = tkey.data;
			user_key.size = tkey.size;
		}

		ret = _gnutls_auth_info_init(session, GNUTLS_CRD_PSK, sizeof(psk_auth_info_st), 1);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
		assert(info != NULL);

		memcpy(info->username, username.data, username.size);
		info->username[username.size] = 0;

		if ((ret = _gnutls_buffer_append_data_prefix(extdata, 16,
							     username.data,
							     username.size)) < 0) {
			gnutls_assert();
			goto cleanup;
		}

		/* Now append the obfuscated ticket age */
		if ((ret = _gnutls_buffer_append_prefix(extdata, 32, 0)) < 0) {
			gnutls_assert();
			goto cleanup;
		}

		psk_id_len += 6 + username.size;
		binders_len += 1 + _gnutls_mac_get_algo_len(prf_psk);
	}

	/* if no tickets or identities to be sent */
	if (psk_id_len == 0) {
		/* reset extensions buffer */
		extdata->length = spos;
		return 0;
	}

	_gnutls_write_uint16(psk_id_len, &extdata->data[spos]);

	binders_pos = extdata->length-spos;
	ext_offset = _gnutls_ext_get_extensions_offset(session);

	/* Compute the binders. extdata->data points to the start
	 * of this client hello. */
	assert(extdata->length >= sizeof(mbuffer_st));
	assert(ext_offset >= (ssize_t)sizeof(mbuffer_st));
	ext_offset -= sizeof(mbuffer_st);
	client_hello.data = extdata->data+sizeof(mbuffer_st);
	client_hello.size = extdata->length-sizeof(mbuffer_st);

	next_idx = 0;

	ret = _gnutls_buffer_append_prefix(extdata, 16, binders_len);
	if (ret < 0) {
		gnutls_assert_val(ret);
		goto cleanup;
	}

	if (prf_res && rkey.size > 0) {
		ret = compute_psk_binder(session, prf_res,
					 binders_len, binders_pos,
					 ext_offset, &rkey, &client_hello, 1,
					 binder_value);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		/* Associate the selected pre-shared key with the session */
		gnutls_free(session->key.binders[next_idx].psk.data);
		session->key.binders[next_idx].psk.data = rkey.data;
		session->key.binders[next_idx].psk.size = rkey.size;
		rkey.data = NULL;

		session->key.binders[next_idx].prf = prf_res;
		session->key.binders[next_idx].resumption = 1;
		session->key.binders[next_idx].idx = next_idx;

		_gnutls_handshake_log("EXT[%p]: sent PSK resumption identity (%d)\n", session, next_idx);

		next_idx++;

		/* Add the binder */
		ret = _gnutls_buffer_append_data_prefix(extdata, 8, binder_value, prf_res->output_size);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		session->internals.hsk_flags |= HSK_TLS13_TICKET_SENT;
	}

	if (prf_psk && user_key.size > 0 && info) {
		ret = compute_psk_binder(session, prf_psk,
					 binders_len, binders_pos,
					 ext_offset, &user_key, &client_hello, 0,
					 binder_value);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		/* Associate the selected pre-shared key with the session */
		gnutls_free(session->key.binders[next_idx].psk.data);
		session->key.binders[next_idx].psk.data = user_key.data;
		session->key.binders[next_idx].psk.size = user_key.size;
		user_key.data = NULL;

		session->key.binders[next_idx].prf = prf_psk;
		session->key.binders[next_idx].resumption = 0;
		session->key.binders[next_idx].idx = next_idx;

		_gnutls_handshake_log("EXT[%p]: sent PSK identity '%s' (%d)\n", session, info->username, next_idx);

		next_idx++;

		/* Add the binder */
		ret = _gnutls_buffer_append_data_prefix(extdata, 8, binder_value, prf_psk->output_size);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}
	}

	ret = 0;

cleanup:
	if (free_username)
		_gnutls_free_datum(&username);

	_gnutls_free_temp_key_datum(&user_key);
	_gnutls_free_temp_key_datum(&rkey);

	return ret;
}
Пример #19
0
int
_gnutls_ext_sr_verify (gnutls_session_t session)
{
  int ret;
  sr_ext_st *priv = NULL;
  extension_priv_data_t epriv;

  if (session->internals.priorities.sr == SR_DISABLED)
    {
      gnutls_assert ();
      return 0;
    }

  ret = _gnutls_ext_get_session_data (session,
                                      GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
                                      &epriv);
  if (ret >= 0)
    priv = epriv.ptr;

  /* Safe renegotiation */

  if (priv && priv->safe_renegotiation_received)
    {
      if ((priv->ri_extension_data_len < priv->client_verify_data_len) ||
          (memcmp (priv->ri_extension_data,
                   priv->client_verify_data, priv->client_verify_data_len)))
        {
          gnutls_assert ();
          _gnutls_handshake_log ("HSK[%p]: Safe renegotiation failed [1]\n",
                                 session);
          return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
        }

      if (session->security_parameters.entity == GNUTLS_CLIENT)
        {
          if ((priv->ri_extension_data_len !=
               priv->client_verify_data_len + priv->server_verify_data_len) ||
              memcmp (priv->ri_extension_data + priv->client_verify_data_len,
                      priv->server_verify_data,
                      priv->server_verify_data_len) != 0)
            {
              gnutls_assert ();
              _gnutls_handshake_log
                ("HSK[%p]: Safe renegotiation failed [2]\n", session);
              return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
            }
        }
      else                      /* Make sure there are 0 extra bytes */
        {
          if (priv->ri_extension_data_len != priv->client_verify_data_len)
            {
              gnutls_assert ();
              _gnutls_handshake_log
                ("HSK[%p]: Safe renegotiation failed [3]\n", session);
              return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
            }
        }

      _gnutls_handshake_log ("HSK[%p]: Safe renegotiation succeeded\n",
                             session);
    }
  else                          /* safe renegotiation not received... */
    {
      if (priv && priv->connection_using_safe_renegotiation)
        {
          gnutls_assert ();
          _gnutls_handshake_log
            ("HSK[%p]: Peer previously asked for safe renegotiation\n",
             session);
          return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
        }

      /* Clients can't tell if it's an initial negotiation */
      if (session->internals.initial_negotiation_completed)
        {
          if (session->internals.priorities.sr < SR_PARTIAL)
            {
              _gnutls_handshake_log
                ("HSK[%p]: Allowing unsafe (re)negotiation\n", session);
            }
          else
            {
              gnutls_assert ();
              _gnutls_handshake_log
                ("HSK[%p]: Denying unsafe (re)negotiation\n", session);
              return GNUTLS_E_UNSAFE_RENEGOTIATION_DENIED;
            }
        }
      else
        {
          if (session->internals.priorities.sr < SR_SAFE)
            {
              _gnutls_handshake_log
                ("HSK[%p]: Allowing unsafe initial negotiation\n", session);
            }
          else
            {
              gnutls_assert ();
              _gnutls_handshake_log
                ("HSK[%p]: Denying unsafe initial negotiation\n", session);
              return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
            }
        }
    }

  return 0;
}
Пример #20
0
/* Do PKCS-1 RSA decryption. 
 * params is modulus, public exp., private key
 * Can decrypt block type 1 and type 2 packets.
 */
int
_gnutls_pkcs1_rsa_decrypt (gnutls_datum_t * plaintext,
			   const gnutls_datum_t * ciphertext,
			   mpi_t * params, unsigned params_len,
			   unsigned btype)
{
  unsigned k, i;
  int ret;
  mpi_t c, res;
  opaque *edata;
  size_t esize, mod_bits;

  mod_bits = _gnutls_mpi_get_nbits (params[0]);
  k = mod_bits / 8;
  if (mod_bits % 8 != 0)
    k++;

  esize = ciphertext->size;

  if (esize != k)
    {
      gnutls_assert ();
      return GNUTLS_E_PK_DECRYPTION_FAILED;
    }

  if (_gnutls_mpi_scan_nz (&c, ciphertext->data, &esize) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  /* we can use btype to see if the private key is
   * available.
   */
  if (btype == 2)
    ret = _gnutls_pk_decrypt (GCRY_PK_RSA, &res, c, params, params_len);
  else
    {
      ret = _gnutls_pk_encrypt (GCRY_PK_RSA, &res, c, params, params_len);
    }
  _gnutls_mpi_release (&c);

  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  _gnutls_mpi_print (NULL, &esize, res);
  edata = gnutls_alloca (esize + 1);
  if (edata == NULL)
    {
      gnutls_assert ();
      _gnutls_mpi_release (&res);
      return GNUTLS_E_MEMORY_ERROR;
    }
  _gnutls_mpi_print (&edata[1], &esize, res);

  _gnutls_mpi_release (&res);

  /* EB = 00||BT||PS||00||D
   * (use block type 'btype')
   *
   * From now on, return GNUTLS_E_DECRYPTION_FAILED on errors, to
   * avoid attacks similar to the one described by Bleichenbacher in:
   * "Chosen Ciphertext Attacks against Protocols Based on RSA
   * Encryption Standard PKCS #1".
   */


  edata[0] = 0;
  esize++;

  if (edata[0] != 0 || edata[1] != btype)
    {
      gnutls_assert ();
      gnutls_afree (edata);
      return GNUTLS_E_DECRYPTION_FAILED;
    }

  ret = GNUTLS_E_DECRYPTION_FAILED;
  switch (btype)
    {
    case 2:
      for (i = 2; i < esize; i++)
	{
	  if (edata[i] == 0)
	    {
	      ret = 0;
	      break;
	    }
	}
      break;
    case 1:
      for (i = 2; i < esize; i++)
	{
	  if (edata[i] == 0 && i > 2)
	    {
	      ret = 0;
	      break;
	    }
	  if (edata[i] != 0xff)
	    {
	      _gnutls_handshake_log ("PKCS #1 padding error");
	      /* PKCS #1 padding error.  Don't use
		 GNUTLS_E_PKCS1_WRONG_PAD here.  */
	      break;
	    }
	}
      break;
    default:
      gnutls_assert ();
      gnutls_afree (edata);
      break;
    }
  i++;

  if (ret < 0)
    {
      gnutls_assert ();
      gnutls_afree (edata);
      return GNUTLS_E_DECRYPTION_FAILED;
    }

  if (_gnutls_sset_datum (plaintext, &edata[i], esize - i) < 0)
    {
      gnutls_assert ();
      gnutls_afree (edata);
      return GNUTLS_E_MEMORY_ERROR;
    }

  gnutls_afree (edata);

  return 0;
}
Пример #21
0
/*
 * In case of a server: if a NAME_DNS extension type is received then
 * it stores into the session the value of NAME_DNS. The server may
 * use gnutls_ext_get_server_name(), in order to access it.
 *
 * In case of a client: If a proper NAME_DNS extension type is found
 * in the session then it sends the extension to the peer.
 *
 */
static int
_gnutls_server_name_recv_params(gnutls_session_t session,
				const uint8_t * data, size_t _data_size)
{
	int i;
	const unsigned char *p;
	uint16_t len, type;
	ssize_t data_size = _data_size;
	int server_names = 0;
	server_name_ext_st *priv;
	extension_priv_data_t epriv;

	if (session->security_parameters.entity == GNUTLS_SERVER) {
		DECR_LENGTH_RET(data_size, 2, 0);
		len = _gnutls_read_uint16(data);

		if (len != data_size) {
			/* This is unexpected packet length, but
			 * just ignore it, for now.
			 */
			gnutls_assert();
			return 0;
		}

		p = data + 2;

		/* Count all server_names in the packet. */
		while (data_size > 0) {
			DECR_LENGTH_RET(data_size, 1, 0);
			p++;

			DECR_LEN(data_size, 2);
			len = _gnutls_read_uint16(p);
			p += 2;

			if (len > 0) {
				DECR_LENGTH_RET(data_size, len, 0);
				server_names++;
				p += len;
			} else
				_gnutls_handshake_log
				    ("HSK[%p]: Received (0) size server name (under attack?)\n",
				     session);

		}

		/* we cannot accept more server names.
		 */
		if (server_names > MAX_SERVER_NAME_EXTENSIONS) {
			_gnutls_handshake_log
			    ("HSK[%p]: Too many server names received (under attack?)\n",
			     session);
			server_names = MAX_SERVER_NAME_EXTENSIONS;
		}

		if (server_names == 0)
			return 0;	/* no names found */

		priv = gnutls_calloc(1, sizeof(*priv));
		if (priv == NULL) {
			gnutls_assert();
			return GNUTLS_E_MEMORY_ERROR;
		}

		priv->server_names_size = server_names;

		p = data + 2;
		for (i = 0; i < server_names; i++) {
			type = *p;
			p++;

			len = _gnutls_read_uint16(p);
			p += 2;

			switch (type) {
			case 0:	/* NAME_DNS */
				if (len < MAX_SERVER_NAME_SIZE) {
					memcpy(priv->server_names[i].name,
					       p, len);
					priv->server_names[i].name[len] = 0;
					priv->server_names[i].name_length =
					    len;
					priv->server_names[i].type =
					    GNUTLS_NAME_DNS;
					break;
				}
			}

			/* move to next record */
			p += len;
		}

		epriv = priv;
		_gnutls_ext_set_session_data(session,
					     GNUTLS_EXTENSION_SERVER_NAME,
					     epriv);

	}

	return 0;
}
Пример #22
0
int
_gnutls_gen_extensions(gnutls_session_t session,
		       gnutls_buffer_st * extdata,
		       gnutls_ext_parse_type_t parse_type)
{
	int size;
	int pos, size_pos, ret;
	size_t i, init_size = extdata->length;

	pos = extdata->length;	/* we will store length later on */

	ret = _gnutls_buffer_append_prefix(extdata, 16, 0);
	if (ret < 0)
		return gnutls_assert_val(ret);

	for (i = 0; i < extfunc_size; i++) {
		extension_entry_st *p = &extfunc[i];

		if (p->send_func == NULL)
			continue;

		if (parse_type != GNUTLS_EXT_ANY
		    && p->parse_type != parse_type)
			continue;

		ret = _gnutls_buffer_append_prefix(extdata, 16, p->type);
		if (ret < 0)
			return gnutls_assert_val(ret);

		size_pos = extdata->length;
		ret = _gnutls_buffer_append_prefix(extdata, 16, 0);
		if (ret < 0)
			return gnutls_assert_val(ret);

		size = p->send_func(session, extdata);
		/* returning GNUTLS_E_INT_RET_0 means to send an empty
		 * extension of this type.
		 */
		if (size > 0 || size == GNUTLS_E_INT_RET_0) {
			if (size == GNUTLS_E_INT_RET_0)
				size = 0;

			/* write the real size */
			_gnutls_write_uint16(size,
					     &extdata->data[size_pos]);

			/* add this extension to the extension list
			 */
			_gnutls_extension_list_add(session, p->type);

			_gnutls_handshake_log
			    ("EXT[%p]: Sending extension %s (%d bytes)\n",
			     session, p->name, size);
		} else if (size < 0) {
			gnutls_assert();
			return size;
		} else if (size == 0)
			extdata->length -= 4;	/* reset type and size */
	}

	/* remove any initial data, and the size of the header */
	size = extdata->length - init_size - 2;

	if (size > 0)
		_gnutls_write_uint16(size, &extdata->data[pos]);
	else if (size == 0)
		extdata->length -= 2;	/* the length bytes */

	return size;
}
Пример #23
0
int
_gnutls_parse_extensions(gnutls_session_t session,
			 gnutls_ext_parse_type_t parse_type,
			 const uint8_t * data, int data_size)
{
	int next, ret;
	int pos = 0;
	uint16_t type;
	const uint8_t *sdata;
	gnutls_ext_recv_func ext_recv;
	uint16_t size;

#ifdef DEBUG
	int i;

	if (session->security_parameters.entity == GNUTLS_CLIENT)
		for (i = 0; i < session->internals.extensions_sent_size;
		     i++) {
			_gnutls_handshake_log
			    ("EXT[%d]: expecting extension '%s'\n",
			     session,
			     _gnutls_extension_get_name(session->internals.
							extensions_sent
							[i]));
		}
#endif

	DECR_LENGTH_RET(data_size, 2, 0);
	next = _gnutls_read_uint16(data);
	pos += 2;

	DECR_LENGTH_RET(data_size, next, 0);

	do {
		DECR_LENGTH_RET(next, 2, 0);
		type = _gnutls_read_uint16(&data[pos]);
		pos += 2;

		if ((ret =
		     _gnutls_extension_list_check(session, type)) < 0) {
			gnutls_assert();
			return ret;
		}

		DECR_LENGTH_RET(next, 2, 0);
		size = _gnutls_read_uint16(&data[pos]);
		pos += 2;

		DECR_LENGTH_RET(next, size, 0);
		sdata = &data[pos];
		pos += size;

		ext_recv = _gnutls_ext_func_recv(type, parse_type);
		if (ext_recv == NULL) {
			_gnutls_handshake_log
			    ("EXT[%p]: Found extension '%s/%d'\n", session,
			     _gnutls_extension_get_name(type), type);

			continue;
		}

		_gnutls_handshake_log
		    ("EXT[%p]: Parsing extension '%s/%d' (%d bytes)\n",
		     session, _gnutls_extension_get_name(type), type,
		     size);

		if ((ret = ext_recv(session, sdata, size)) < 0) {
			gnutls_assert();
			return ret;
		}

	}
	while (next > 2);

	return 0;

}
Пример #24
0
static int _proxyinfo_recv_params (gnutls_session_t session, const opaque * data,
                          size_t _data_size)
{
//printf("Recv params\n");
  int i;
  const unsigned char *p;
  uint16_t len, type;
  ssize_t data_size = _data_size;
  int server_names = 0;
  ProxyInfo_ext_st *priv;
  extension_priv_data_t epriv;

  if (session->security_parameters.entity == GNUTLS_SERVER)
    {
      DECR_LENGTH_RET (data_size, 2, 0);
      len = _gnutls_read_uint16 (data);

      if (len != data_size)
        {
          /* This is unexpected packet length, but
           * just ignore it, for now.
           */
          gnutls_assert ();
          return 0;
        }

      p = data + 2;

      
      DECR_LEN (data_size, 2);
      unsigned count = _gnutls_read_uint16 (p);
      p+=2;
      printf("Received Proxy_Info for %d intermediate proxies\n",count+1);
      priv = gnutls_calloc (1, sizeof (*priv));
      if (priv == NULL)
        {
          gnutls_assert ();
          return GNUTLS_E_MEMORY_ERROR;
        }
      priv->proxy_cnt=count;
      
      for (int proxy_id=0;proxy_id<count+1;proxy_id++){
      DECR_LEN (data_size, 2);
      unsigned cipher_algo = _gnutls_read_uint16 (p);
      p+=2;
      DECR_LEN (data_size, 2);
      unsigned kx_algo = _gnutls_read_uint16 (p);
      p+=2;
      DECR_LEN (data_size, 2);
      unsigned mac_algo = _gnutls_read_uint16 (p);
      p+=2;
      DECR_LEN (data_size, 2);
      unsigned ip_addr = _gnutls_read_uint16 (p);
      p+=2;
      DECR_LEN (data_size, 2);
      unsigned mac_addr = _gnutls_read_uint16 (p);
      p+=2;
      //printf("%d %d %d %d %d\n",cipher_algo,kx_algo,mac_algo,ip_addr,mac_addr);

      priv->proxy_info[proxy_id].cipher_algo=cipher_algo;
      priv->proxy_info[proxy_id].kx_algo=kx_algo;
      priv->proxy_info[proxy_id].mac_algo=mac_algo;
      priv->proxy_info[proxy_id].ip_addr=ip_addr;
      priv->proxy_info[proxy_id].mac_addr=mac_addr;
}
      printf("Stored the proxy_info to local instance of extension...\n");
      /* Count all server_names in the packet. */
      while (data_size > 0)
        {
          DECR_LENGTH_RET (data_size, 1, 0);
          p++;

          DECR_LEN (data_size, 2);
          len = _gnutls_read_uint16 (p);
          p += 2;

          if (len > 0)
            {
              DECR_LENGTH_RET (data_size, len, 0);
              server_names++;
              p += len;
            }
          else
            _gnutls_handshake_log
              ("HSK[%p]: Received (0) size server name (under attack?)\n",
               session);

        }

      /* we cannot accept more server names.
       */
      if (server_names > MAX_SERVER_NAME_EXTENSIONS)
        {
          _gnutls_handshake_log
            ("HSK[%p]: Too many server names received (under attack?)\n",
             session);
          server_names = MAX_SERVER_NAME_EXTENSIONS;
        }

      if (server_names == 0)
        return 0;               /* no names found */


      priv->server_names_size = server_names;

      p = data + 4;
      p+=10*(count+1);
      for (i = 0; i < server_names; i++)
        {
          type = *p;
          p++;

          len = _gnutls_read_uint16 (p);
          p += 2;

          switch (type)
            {
            case 0:            /* NAME_DNS */
              if (len <= MAX_SERVER_NAME_SIZE)
                {
                  memcpy (priv->server_names[i].name, p, len);
                  priv->server_names[i].name_length = len;
                  priv->server_names[i].type = GNUTLS_NAME_DNS;
                  break;
                }
            }

          /* move to next record */
          p += len;
        }

      epriv.ptr = priv;
      _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_PROXYINFO,
                                    epriv);

    }

  return 0;
     }
Пример #25
0
/*
 * Return values for this function:
 *  -  0 : Not applicable.
 *  - >0 : Ok. Return size of extension data.
 *  - <0 : There's been an error.
 */
static int _gnutls_psk_recv_params(gnutls_session_t session,
				   const unsigned char *data, size_t len)
{
	unsigned i;
	gnutls_psk_server_credentials_t pskcred;
	const version_entry_st *vers = get_version(session);
	int ret;

	if (!vers || !vers->tls13_sem)
		return 0;

	if (session->security_parameters.entity == GNUTLS_CLIENT) {
		if (session->internals.hsk_flags & HSK_PSK_KE_MODES_SENT) {
			uint16_t selected_identity = _gnutls_read_uint16(data);

			for (i=0;i<sizeof(session->key.binders)/sizeof(session->key.binders[0]);i++) {
				if (session->key.binders[i].prf != NULL && session->key.binders[i].idx == selected_identity) {
					if (session->key.binders[i].resumption) {
						session->internals.resumed = RESUME_TRUE;
						_gnutls_handshake_log("EXT[%p]: selected PSK-resumption mode\n", session);
					} else {
						_gnutls_handshake_log("EXT[%p]: selected PSK mode\n", session);
					}

					/* different PSK is selected, than the one we calculated early secrets */
					if (i != 0) {
						/* ensure that selected binder is set on (our) index zero */
						swap_binders(session);

						ret = _gnutls_generate_early_secrets_for_psk(session);
						if (ret < 0)
							return gnutls_assert_val(ret);
					}
					session->internals.hsk_flags |= HSK_PSK_SELECTED;
				}
			}

			return 0;
		} else {
			return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION);
		}
	} else {
		if (session->internals.hsk_flags & HSK_PSK_KE_MODES_RECEIVED) {
			if (session->internals.hsk_flags & HSK_PSK_KE_MODE_INVALID) {
				/* We received a "psk_ke_modes" extension, but with a value we don't support */
				return 0;
			}

			pskcred = (gnutls_psk_server_credentials_t)
					_gnutls_get_cred(session, GNUTLS_CRD_PSK);

			/* If there are no PSK credentials, this extension is not applicable,
			 * so we return zero. */
			if (pskcred == NULL && (session->internals.flags & GNUTLS_NO_TICKETS))
				return 0;

			return server_recv_params(session, data, len, pskcred);
		} else {
			return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION);
		}
	}
}
Пример #26
0
static int server_recv_params(gnutls_session_t session,
			      const unsigned char *data, size_t len,
			      const gnutls_psk_server_credentials_t pskcred)
{
	int ret;
	const mac_entry_st *prf;
	gnutls_datum_t full_client_hello;
	uint8_t binder_value[MAX_HASH_SIZE];
	uint16_t psk_index, i;
	gnutls_datum_t binder_recvd = { NULL, 0 };
	gnutls_datum_t key = {NULL, 0};
	psk_ext_parser_st psk_parser;
	psk_ext_iter_st psk_iter;
	struct psk_st psk;
	psk_auth_info_t info;
	tls13_ticket_st ticket_data;
	/* These values should be set properly when session ticket is accepted. */
	uint32_t ticket_age = UINT32_MAX;
	struct timespec ticket_creation_time = { 0, 0 };
	bool resuming;

	ret = _gnutls13_psk_ext_parser_init(&psk_parser, data, len);
	if (ret < 0) {
		/* No PSKs advertised by client */
		if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
			return 0;
		return gnutls_assert_val(ret);
	}

	_gnutls13_psk_ext_iter_init(&psk_iter, &psk_parser);
	for (psk_index = 0; ; psk_index++) {
		ret = _gnutls13_psk_ext_iter_next_identity(&psk_iter, &psk);
		if (ret < 0) {
			/* We couldn't find any usable PSK */
			if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
				return 0;
			return gnutls_assert_val(ret);
		}

		/* This will unpack the session ticket if it is well
		 * formed and has the expected name */
		if (!(session->internals.flags & GNUTLS_NO_TICKETS) &&
		    (ret = _gnutls13_unpack_session_ticket(session, &psk.identity, &ticket_data)) == 0) {
			prf = ticket_data.prf;

			session->internals.resumption_requested = 1;

			/* Check whether ticket is stale or not */
			ticket_age = psk.ob_ticket_age - ticket_data.age_add;
			if (ticket_age / 1000 > ticket_data.lifetime) {
				gnutls_assert();
				tls13_ticket_deinit(&ticket_data);
				continue;
			}

			ret = compute_psk_from_ticket(&ticket_data, &key);
			if (ret < 0) {
				gnutls_assert();
				tls13_ticket_deinit(&ticket_data);
				continue;
			}

			memcpy(&ticket_creation_time,
			       &ticket_data.creation_time,
			       sizeof(struct timespec));

			tls13_ticket_deinit(&ticket_data);

			resuming = 1;
			break;
		} else if (pskcred &&
			   psk.ob_ticket_age == 0 &&
			   psk.identity.size > 0 && psk.identity.size <= MAX_USERNAME_SIZE) {
			/* _gnutls_psk_pwd_find_entry() expects 0-terminated identities */
			char identity_str[MAX_USERNAME_SIZE + 1];

			prf = pskcred->binder_algo;

			memcpy(identity_str, psk.identity.data, psk.identity.size);
			identity_str[psk.identity.size] = 0;

			/* this fails only on configuration errors; as such we always
			 * return its error code in that case */
			ret = _gnutls_psk_pwd_find_entry(session, identity_str, &key);
			if (ret < 0)
				return gnutls_assert_val(ret);

			resuming = 0;
			break;
		}
	}

	_gnutls13_psk_ext_iter_init(&psk_iter, &psk_parser);
	for (i = 0; i <= psk_index; i++) {
		ret = _gnutls13_psk_ext_iter_next_binder(&psk_iter, &binder_recvd);
		if (ret < 0) {
			gnutls_assert();
			/* We couldn't extract binder */
			if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
				ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
			goto fail;
		}
	}

	/* Get full ClientHello */
	if (!_gnutls_ext_get_full_client_hello(session, &full_client_hello)) {
		ret = GNUTLS_E_INTERNAL_ERROR;
		gnutls_assert();
		goto fail;
	}

	/* Compute the binder value for this PSK */
	ret = compute_psk_binder(session, prf, psk_parser.binders_len+2, 0, 0,
				 &key, &full_client_hello, resuming,
				 binder_value);
	if (ret < 0) {
		gnutls_assert();
		goto fail;
	}

	if (_gnutls_mac_get_algo_len(prf) != binder_recvd.size ||
	    safe_memcmp(binder_value, binder_recvd.data, binder_recvd.size)) {
		gnutls_assert();
		ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
		goto fail;
	}

	if (session->internals.hsk_flags & HSK_PSK_KE_MODE_DHE_PSK)
		_gnutls_handshake_log("EXT[%p]: selected DHE-PSK mode\n", session);
	else {
		reset_cand_groups(session);
		_gnutls_handshake_log("EXT[%p]: selected PSK mode\n", session);
	}

	/* save the username in psk_auth_info to make it available
	 * using gnutls_psk_server_get_username() */
	if (!resuming) {
		assert(psk.identity.size < sizeof(info->username));

		ret = _gnutls_auth_info_init(session, GNUTLS_CRD_PSK, sizeof(psk_auth_info_st), 1);
		if (ret < 0) {
			gnutls_assert();
			goto fail;
		}

		info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
		assert(info != NULL);

		memcpy(info->username, psk.identity.data, psk.identity.size);
		info->username[psk.identity.size] = 0;
		_gnutls_handshake_log("EXT[%p]: selected PSK identity: %s (%d)\n", session, info->username, psk_index);
	} else {
		if (session->internals.hsk_flags & HSK_EARLY_DATA_ACCEPTED) {
			if (session->internals.anti_replay) {
				ret = _gnutls_anti_replay_check(session->internals.anti_replay,
								ticket_age,
								&ticket_creation_time,
								&binder_recvd);
				if (ret < 0) {
					session->internals.hsk_flags &= ~HSK_EARLY_DATA_ACCEPTED;
					_gnutls_handshake_log("EXT[%p]: replay detected; rejecting early data\n",
						      session);
				}
			} else {
				_gnutls_handshake_log("EXT[%p]: anti-replay is not enabled; rejecting early data\n",
						      session);
				session->internals.hsk_flags &= ~HSK_EARLY_DATA_ACCEPTED;
			}
		}

		session->internals.resumed = RESUME_TRUE;
		_gnutls_handshake_log("EXT[%p]: selected resumption PSK identity (%d)\n", session, psk_index);
	}

	session->internals.hsk_flags |= HSK_PSK_SELECTED;

	/* Reference the selected pre-shared key */
	session->key.binders[0].psk.data = key.data;
	session->key.binders[0].psk.size = key.size;

	session->key.binders[0].idx = psk_index;
	session->key.binders[0].prf = prf;
	session->key.binders[0].resumption = resuming;

	ret = _gnutls_generate_early_secrets_for_psk(session);
	if (ret < 0) {
		gnutls_assert();
		goto fail;
	}

	return 0;

 fail:
	gnutls_free(key.data);
	return ret;
}
Пример #27
0
/* Do PKCS-1 RSA decryption. 
 * params is modulus, public exp., private key
 * Can decrypt block type 1 and type 2 packets.
 */
int
_gnutls_pkcs1_rsa_decrypt (gnutls_datum_t * plaintext,
			   const gnutls_datum_t * ciphertext,
			   bigint_t * params, unsigned params_len,
			   unsigned btype)
{
  unsigned int k, i;
  int ret;
  size_t esize, mod_bits;
  gnutls_pk_params_st pk_params;

  for (i = 0; i < params_len; i++)
    pk_params.params[i] = params[i];
  pk_params.params_nr = params_len;

  mod_bits = _gnutls_mpi_get_nbits (params[0]);
  k = mod_bits / 8;
  if (mod_bits % 8 != 0)
    k++;

  esize = ciphertext->size;

  if (esize != k)
    {
      gnutls_assert ();
      return GNUTLS_E_PK_DECRYPTION_FAILED;
    }

  /* we can use btype to see if the private key is
   * available.
   */
  if (btype == 2)
    {
      ret =
	_gnutls_pk_decrypt (GNUTLS_PK_RSA, plaintext, ciphertext, &pk_params);
    }
  else
    {
      ret =
	_gnutls_pk_encrypt (GNUTLS_PK_RSA, plaintext, ciphertext, &pk_params);
    }

  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  /* EB = 00||BT||PS||00||D
   * (use block type 'btype')
   *
   * From now on, return GNUTLS_E_DECRYPTION_FAILED on errors, to
   * avoid attacks similar to the one described by Bleichenbacher in:
   * "Chosen Ciphertext Attacks against Protocols Based on RSA
   * Encryption Standard PKCS #1".
   */
  if (plaintext->data[0] != 0 || plaintext->data[1] != btype)
    {
      gnutls_assert ();
      return GNUTLS_E_DECRYPTION_FAILED;
    }

  ret = GNUTLS_E_DECRYPTION_FAILED;
  switch (btype)
    {
    case 2:
      for (i = 2; i < plaintext->size; i++)
	{
	  if (plaintext->data[i] == 0)
	    {
	      ret = 0;
	      break;
	    }
	}
      break;
    case 1:
      for (i = 2; i < plaintext->size; i++)
	{
	  if (plaintext->data[i] == 0 && i > 2)
	    {
	      ret = 0;
	      break;
	    }
	  if (plaintext->data[i] != 0xff)
	    {
	      _gnutls_handshake_log ("PKCS #1 padding error");
	      _gnutls_free_datum (plaintext);
	      /* PKCS #1 padding error.  Don't use
	         GNUTLS_E_PKCS1_WRONG_PAD here.  */
	      break;
	    }
	}
      break;
    default:
      gnutls_assert ();
      _gnutls_free_datum (plaintext);
      break;
    }
  i++;

  if (ret < 0)
    {
      gnutls_assert ();
      _gnutls_free_datum (plaintext);
      return GNUTLS_E_DECRYPTION_FAILED;
    }

  memmove (plaintext->data, &plaintext->data[i], esize - i);
  plaintext->size = esize - i;

  return 0;
}
Пример #28
0
int _gnutls13_recv_certificate(gnutls_session_t session)
{
	int ret;
	gnutls_buffer_st buf;
	unsigned optional = 0;

	if (!session->internals.initial_negotiation_completed &&
	    session->internals.hsk_flags & HSK_PSK_SELECTED)
		return 0;

	if (session->security_parameters.entity == GNUTLS_SERVER) {
		/* if we didn't request a certificate, there will not be any */
		if (session->internals.send_cert_req == 0)
			return 0;

		if (session->internals.send_cert_req != GNUTLS_CERT_REQUIRE)
			optional = 1;
	}

	ret = _gnutls_recv_handshake(session, GNUTLS_HANDSHAKE_CERTIFICATE_PKT, 0, &buf);
	if (ret < 0) {
		if (ret == GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET && session->internals.send_cert_req)
			return gnutls_assert_val(GNUTLS_E_NO_CERTIFICATE_FOUND);

		return gnutls_assert_val(ret);
	}

	if (buf.length == 0) {
		gnutls_assert();
		ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
		goto cleanup;
	}

	if (session->internals.initial_negotiation_completed &&
	    session->internals.post_handshake_cr_context.size > 0) {
		gnutls_datum_t context;

		/* verify whether the context matches */
		ret = _gnutls_buffer_pop_datum_prefix8(&buf, &context);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		if (context.size != session->internals.post_handshake_cr_context.size ||
		    memcmp(context.data, session->internals.post_handshake_cr_context.data,
		           context.size) != 0) {
			ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
			gnutls_assert();
			goto cleanup;
		}
	} else {
		if (buf.data[0] != 0) {
			/* The context field must be empty during handshake */
			gnutls_assert();
			ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
			goto cleanup;
		}

		/* buf.length is positive */
		buf.data++;
		buf.length--;
	}

	_gnutls_handshake_log("HSK[%p]: parsing certificate message\n", session);

	ret = parse_cert_list(session, buf.data, buf.length);
	if (ret < 0) {
		if (ret == GNUTLS_E_NO_CERTIFICATE_FOUND) {
			if (optional)
				ret = 0;
			else if (session->security_parameters.entity ==
				 GNUTLS_SERVER)
				ret = GNUTLS_E_CERTIFICATE_REQUIRED;
		}
		gnutls_assert();
		goto cleanup;
	}

	session->internals.hsk_flags |= HSK_CRT_VRFY_EXPECTED;

	ret = 0;
cleanup:

	_gnutls_buffer_clear(&buf);
	return ret;
}
Пример #29
0
static int
parse_handshake_header(gnutls_session_t session, mbuffer_st * bufel,
		       handshake_buffer_st * hsk)
{
	uint8_t *dataptr = NULL;	/* for realloc */
	size_t handshake_header_size =
	    HANDSHAKE_HEADER_SIZE(session), data_size, frag_size;

	/* Note: SSL2_HEADERS == 1 */
	if (_mbuffer_get_udata_size(bufel) < handshake_header_size)
		return
		    gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);

	dataptr = _mbuffer_get_udata_ptr(bufel);

	/* if reading a client hello of SSLv2 */
#ifdef ENABLE_SSL2
	if (unlikely
	    (!IS_DTLS(session)
	     && bufel->htype == GNUTLS_HANDSHAKE_CLIENT_HELLO_V2)) {
		handshake_header_size = SSL2_HEADERS;	/* we've already read one byte */

		frag_size = _mbuffer_get_udata_size(bufel) - handshake_header_size;	/* we've read the first byte */

		if (dataptr[0] != GNUTLS_HANDSHAKE_CLIENT_HELLO)
			return
			    gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);

		hsk->rtype = hsk->htype = GNUTLS_HANDSHAKE_CLIENT_HELLO_V2;

		hsk->sequence = 0;
		hsk->start_offset = 0;
		hsk->length = frag_size;
	} else
#endif
	{	/* TLS or DTLS handshake headers */


		hsk->rtype = hsk->htype = dataptr[0];

		/* we do not use DECR_LEN because we know
		 * that the packet has enough data.
		 */
		hsk->length = _gnutls_read_uint24(&dataptr[1]);

		if (IS_DTLS(session)) {
			hsk->sequence = _gnutls_read_uint16(&dataptr[4]);
			hsk->start_offset =
			    _gnutls_read_uint24(&dataptr[6]);
			frag_size =
			    _gnutls_read_uint24(&dataptr[9]);
		} else {
			hsk->sequence = 0;
			hsk->start_offset = 0;
			frag_size =
			    MIN((_mbuffer_get_udata_size(bufel) -
				 handshake_header_size), hsk->length);
		}

		/* TLS1.3: distinguish server hello versus hello retry request.
		 * The epitome of slick protocol design. */
		if (hsk->htype == GNUTLS_HANDSHAKE_SERVER_HELLO && hsk->start_offset == 0 && !IS_DTLS(session)) {
			if (_mbuffer_get_udata_size(bufel) > handshake_header_size+2+GNUTLS_RANDOM_SIZE &&
			    memcmp(dataptr+handshake_header_size+2, HRR_RANDOM, GNUTLS_RANDOM_SIZE) == 0) {
				hsk->htype = GNUTLS_HANDSHAKE_HELLO_RETRY_REQUEST;
			}
		}
	}
	data_size = _mbuffer_get_udata_size(bufel) - handshake_header_size;

	if (frag_size > 0)
		hsk->end_offset = hsk->start_offset + frag_size - 1;
	else
		hsk->end_offset = 0;

	_gnutls_handshake_log
	    ("HSK[%p]: %s (%u) was received. Length %d[%d], frag offset %d, frag length: %d, sequence: %d\n",
	     session, _gnutls_handshake2str(hsk->htype),
	     (unsigned) hsk->htype, (int) hsk->length, (int) data_size,
	     hsk->start_offset, (int) frag_size,
	     (int) hsk->sequence);

	hsk->header_size = handshake_header_size;
	memcpy(hsk->header, _mbuffer_get_udata_ptr(bufel),
	       handshake_header_size);

	if (hsk->length > 0 && (frag_size > data_size ||
				(frag_size > 0 &&
				 hsk->end_offset >= hsk->length))) {
		return
		    gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
	}
	else if (hsk->length == 0 && hsk->end_offset != 0
		 && hsk->start_offset != 0)
		return
		    gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);

	return handshake_header_size;
}
Пример #30
0
int _gnutls_recv_server_certificate_status(gnutls_session_t session)
{
	uint8_t *data;
	int data_size;
	size_t r_size;
	gnutls_buffer_st buf;
	int ret;
	status_request_ext_st *priv = NULL;
	extension_priv_data_t epriv;

	ret =
	    _gnutls_ext_get_session_data(session,
					 GNUTLS_EXTENSION_STATUS_REQUEST,
					 &epriv);
	if (ret < 0)
		return 0;

	priv = epriv.ptr;

	if (!priv->expect_cstatus)
		return 0;

	ret = _gnutls_recv_handshake(session,
				     GNUTLS_HANDSHAKE_CERTIFICATE_STATUS,
				     0, &buf);
	if (ret < 0)
		return gnutls_assert_val_fatal(ret);

	priv->expect_cstatus = 0;

	data = buf.data;
	data_size = buf.length;

	/* minimum message is type (1) + response (3) + data */
	if (data_size == 0)
		return 0;
	else if (data_size < 4)
		return
		    gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);

	if (data[0] != 0x01) {
		gnutls_assert();
		_gnutls_handshake_log("EXT[%p]: unknown status_type %d\n",
				      session, data[0]);
		return 0;
	}
	DECR_LENGTH_COM(data_size, 1, ret =
			GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
			goto error);
	data++;

	DECR_LENGTH_COM(data_size, 3, ret =
			GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
			goto error);
	r_size = _gnutls_read_uint24(data);
	data += 3;

	DECR_LENGTH_COM(data_size, r_size, ret =
			GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
			goto error);

	ret = _gnutls_set_datum(&priv->response, data, r_size);
	if (ret < 0)
		goto error;

	ret = 0;

      error:
	_gnutls_buffer_clear(&buf);

	return ret;
}