示例#1
0
/* this function reads a (small) unsigned integer
 * from asn1 structs. Combines the read and the convertion
 * steps.
 */
int
_gnutls_x509_read_uint (ASN1_TYPE node, const char *value, unsigned int *ret)
{
  int len, result;
  opaque *tmpstr;

  len = 0;
  result = asn1_read_value (node, value, NULL, &len);
  if (result != ASN1_MEM_ERROR)
    {
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }

  tmpstr = gnutls_malloc (len);
  if (tmpstr == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  result = asn1_read_value (node, value, tmpstr, &len);

  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      gnutls_free (tmpstr);
      return _gnutls_asn2err (result);
    }

  if (len == 1)
    *ret = tmpstr[0];
  else if (len == 2)
    *ret = _gnutls_read_uint16 (tmpstr);
  else if (len == 3)
    *ret = _gnutls_read_uint24 (tmpstr);
  else if (len == 4)
    *ret = _gnutls_read_uint32 (tmpstr);
  else
    {
      gnutls_assert ();
      gnutls_free (tmpstr);
      return GNUTLS_E_INTERNAL_ERROR;
    }

  gnutls_free (tmpstr);

  return 0;
}
示例#2
0
/* Receive TLS/IA data.  Store received TLS/IA message type in
   *MSG_TYPE, and the data in DATA of max SIZEOFDATA size.  Return the
   number of bytes read, or an error code. */
static ssize_t
_gnutls_recv_inner_application (gnutls_session_t session,
				gnutls_ia_apptype_t * msg_type,
				opaque * data, size_t sizeofdata)
{
  ssize_t len;
  uint32_t len24;
  opaque pkt[4];

  len = _gnutls_recv_int (session, GNUTLS_INNER_APPLICATION, -1, pkt, 4);
  if (len != 4)
    {
      gnutls_assert ();
      return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
    }

  *msg_type = pkt[0];
  len24 = _gnutls_read_uint24 (&pkt[1]);

  if (*msg_type != GNUTLS_IA_APPLICATION_PAYLOAD && len24 != CHECKSUM_SIZE)
    {
      gnutls_assert ();
      return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
    }

  if (sizeofdata < len24)
    {
      /* XXX push back pkt to IA buffer? */
      gnutls_assert ();
      return GNUTLS_E_SHORT_MEMORY_BUFFER;
    }

  if (len24 > 0)
    {
      uint32_t tmplen = len24;

      len24 = _gnutls_recv_int (session, GNUTLS_INNER_APPLICATION, -1,
				data, tmplen);
      if (len24 != tmplen)
	{
	  gnutls_assert ();
	  /* XXX Correct? */
	  return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
	}
    }

  return len24;
}
示例#3
0
文件: buffers.c 项目: gnutls/gnutls
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;
}
示例#4
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;
}
示例#5
0
static int
parse_cert_list(gnutls_session_t session, uint8_t * data, size_t data_size)
{
	int len, ret;
	uint8_t *p = data;
	cert_auth_info_t info;
	gnutls_certificate_credentials_t cred;
	ssize_t dsize = data_size, size;
	int i;
	unsigned npeer_certs, npeer_ocsp, j;
	crt_cert_ctx_st ctx;
	gnutls_datum_t *peer_certs = NULL;
	gnutls_datum_t *peer_ocsp = NULL;
	unsigned nentries = 0;

	cred = (gnutls_certificate_credentials_t)
	    _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE);
	if (cred == NULL) {
		gnutls_assert();
		return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
	}

	if ((ret =
	     _gnutls_auth_info_init(session, GNUTLS_CRD_CERTIFICATE,
				   sizeof(cert_auth_info_st), 1)) < 0) {
		gnutls_assert();
		return ret;
	}

	if (data == NULL || data_size == 0) {
		/* no certificate was sent */
		return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
	}

	info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
	if (info == NULL)
		return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);

	DECR_LEN(dsize, 3);
	size = _gnutls_read_uint24(p);
	p += 3;

	if (size != dsize)
		return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);

	if (size == 0)
		return gnutls_assert_val(GNUTLS_E_NO_CERTIFICATE_FOUND);

	i = dsize;

	while (i > 0) {
		DECR_LEN(dsize, 3);
		len = _gnutls_read_uint24(p);
		if (len == 0)
			return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);

		DECR_LEN(dsize, len);
		p += len + 3;
		i -= len + 3;

		DECR_LEN(dsize, 2);
		len = _gnutls_read_uint16(p);
		DECR_LEN(dsize, len);

		i -= len + 2;
		p += len + 2;

		nentries++;
	}

	if (dsize != 0)
		return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);

	/* this is unnecessary - keeping to avoid a regression due to a re-org
	 * of the loop above */
	if (nentries == 0)
		return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);

	npeer_ocsp = 0;
	npeer_certs = 0;

	/* Ok we now allocate the memory to hold the
	 * certificate list
	 */
	peer_certs = gnutls_calloc(nentries, sizeof(gnutls_datum_t));
	if (peer_certs == NULL)
		return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

	peer_ocsp = gnutls_calloc(nentries, sizeof(gnutls_datum_t));
	if (peer_ocsp == NULL) {
		ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
		goto cleanup;
	}

	p = data+3;

	/* Now we start parsing the list (again).
	 * We don't use DECR_LEN since the list has
	 * been parsed before.
	 */

	ctx.session = session;

	for (j = 0; j < nentries; j++) {
		len = _gnutls_read_uint24(p);
		p += 3;

		ret = _gnutls_set_datum(&peer_certs[j], p, len);
		if (ret < 0) {
			gnutls_assert();
			ret = GNUTLS_E_CERTIFICATE_ERROR;
			goto cleanup;
		}
		npeer_certs++;

		p += len;

		len = _gnutls_read_uint16(p);

		ctx.ocsp = &peer_ocsp[j];
		ctx.idx = j;

		ret = _gnutls_extv_parse(&ctx, parse_cert_extension, p, len+2);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		p += len+2;
		npeer_ocsp++;
	}

	/* The OCSP entries match the certificate entries, although
	 * the contents of each OCSP entry may be NULL.
	 */
	for(j=0;j<info->ncerts;j++)
		gnutls_free(info->raw_certificate_list[j].data);
	gnutls_free(info->raw_certificate_list);

	for(j=0;j<info->nocsp;j++)
		gnutls_free(info->raw_ocsp_list[j].data);
	gnutls_free(info->raw_ocsp_list);


	info->raw_certificate_list = peer_certs;
	info->ncerts = npeer_certs;

	info->raw_ocsp_list = peer_ocsp;
	info->nocsp = npeer_ocsp;

	return 0;

 cleanup:
	for(j=0;j<npeer_certs;j++)
		gnutls_free(peer_certs[j].data);

	for(j=0;j<npeer_ocsp;j++)
		gnutls_free(peer_ocsp[j].data);
	gnutls_free(peer_certs);
	gnutls_free(peer_ocsp);
	return ret;

}
示例#6
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;
}