예제 #1
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 (session->security_parameters.entity == GNUTLS_CLIENT) {
			if ((ret =
			     _gnutls_extension_list_check(session, type)) < 0) {
				gnutls_assert();
				return ret;
			}
		} else {
			_gnutls_extension_list_add(session, type);
		}

		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;

}
예제 #2
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], major, minor;
	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]);

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

	adv_version = _gnutls_version_get(major, minor);

	ret = _gnutls_negotiate_version(session, adv_version, major, minor);
	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, major, minor);
	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;
	}

	ret = _gnutls_set_compression(session, GNUTLS_COMP_NULL);
	if (ret < 0)
		return gnutls_assert_val(ret);

	return sret;
}
예제 #3
0
/*
 * Processes a heartbeat message. 
 */
int _gnutls_heartbeat_handle(gnutls_session_t session, mbuffer_st * bufel)
{
	int ret;
	unsigned type;
	unsigned pos;
	uint8_t *msg = _mbuffer_get_udata_ptr(bufel);
	size_t hb_len, len = _mbuffer_get_udata_size(bufel);

	if (gnutls_heartbeat_allowed
	    (session, GNUTLS_HB_PEER_ALLOWED_TO_SEND) == 0)
		return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);

	if (len < 4)
		return
		    gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);

	pos = 0;
	type = msg[pos++];

	hb_len = _gnutls_read_uint16(&msg[pos]);
	if (hb_len > len - 3)
		return
		    gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);

	pos += 2;

	switch (type) {
	case HEARTBEAT_REQUEST:
		_gnutls_buffer_reset(&session->internals.hb_remote_data);

		ret =
		    _gnutls_buffer_resize(&session->internals.
					  hb_remote_data, hb_len);
		if (ret < 0)
			return gnutls_assert_val(ret);

		if (hb_len > 0)
			memcpy(session->internals.hb_remote_data.data,
			       &msg[pos], hb_len);
		session->internals.hb_remote_data.length = hb_len;

		return gnutls_assert_val(GNUTLS_E_HEARTBEAT_PING_RECEIVED);

	case HEARTBEAT_RESPONSE:

		if (hb_len != session->internals.hb_local_data.length)
			return
			    gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);

		if (hb_len > 0 &&
		    memcmp(&msg[pos],
			   session->internals.hb_local_data.data,
			   hb_len) != 0) {
			if (IS_DTLS(session))
				return gnutls_assert_val(GNUTLS_E_AGAIN);	/* ignore it */
			else
				return
				    gnutls_assert_val
				    (GNUTLS_E_UNEXPECTED_PACKET);
		}

		_gnutls_buffer_reset(&session->internals.hb_local_data);

		return gnutls_assert_val(GNUTLS_E_HEARTBEAT_PONG_RECEIVED);
	default:
		_gnutls_record_log
		    ("REC[%p]: HB: received unknown type %u\n", session,
		     type);
		return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
	}
}
예제 #4
0
/*
 * Return zero if session tickets haven't been enabled.
 */
int _gnutls_recv_new_session_ticket(gnutls_session_t session)
{
	uint8_t *p;
	int data_size;
	gnutls_buffer_st buf;
	uint16_t ticket_len;
	int ret;
	session_ticket_ext_st *priv = NULL;
	gnutls_ext_priv_data_t epriv;

	if (session->internals.flags & GNUTLS_NO_TICKETS)
		return 0;
	if (!session->internals.session_ticket_renew)
		return 0;

	/* This is the last flight and peer cannot be sure
	 * we have received it unless we notify him. So we
	 * wait for a message and retransmit if needed. */
	if (IS_DTLS(session) && !_dtls_is_async(session)) {
		unsigned have;
		mbuffer_st *bufel = NULL;

		have = gnutls_record_check_pending(session) +
		       record_check_unprocessed(session);

		if (have != 0) {
			bufel = _mbuffer_head_get_first(&session->internals.record_buffer, NULL);
		}

		if (have == 0 || (bufel && bufel->type != GNUTLS_HANDSHAKE)) {
			ret = _dtls_wait_and_retransmit(session);
			if (ret < 0)
				return gnutls_assert_val(ret);
		}
	}

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

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

	DECR_LENGTH_COM(data_size, 4, ret =
			GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
			goto error);
	/* skip over lifetime hint */
	p += 4;

	DECR_LENGTH_COM(data_size, 2, ret =
			GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
			goto error);
	ticket_len = _gnutls_read_uint16(p);
	p += 2;

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

	priv = gnutls_calloc(1, sizeof(*priv));
	if (!priv) {
		gnutls_assert();
		ret = GNUTLS_E_MEMORY_ERROR;
		goto error;
	}
	priv->session_ticket =
	    gnutls_realloc_fast(priv->session_ticket, ticket_len);
	if (!priv->session_ticket) {
		gnutls_free(priv);
		gnutls_assert();
		ret = GNUTLS_E_MEMORY_ERROR;
		goto error;
	}
	memcpy(priv->session_ticket, p, ticket_len);
	priv->session_ticket_len = ticket_len;
	epriv = priv;

	/* Discard the current session ID.  (RFC5077 3.4) */
	ret =
	    _gnutls_generate_session_id(session->security_parameters.
					session_id,
					&session->security_parameters.
					session_id_size);
	if (ret < 0) {
		gnutls_assert();
		session_ticket_deinit_data(epriv);
		ret = GNUTLS_E_INTERNAL_ERROR;
		goto error;
	}
	ret = 0;

	_gnutls_handshake_log
		    ("HSK[%p]: received session ticket\n", session);
	session->internals.hsk_flags |= HSK_TICKET_RECEIVED;

	_gnutls_hello_ext_set_priv(session,
			GNUTLS_EXTENSION_SESSION_TICKET,
			epriv);

      error:
	_gnutls_buffer_clear(&buf);

	return ret;
}
예제 #5
0
static int
session_ticket_recv_params(gnutls_session_t session,
                           const uint8_t * data, size_t _data_size)
{
    ssize_t data_size = _data_size;
    session_ticket_ext_st *priv = NULL;
    extension_priv_data_t epriv;
    int ret;

    ret =
        _gnutls_ext_get_session_data(session,
                                     GNUTLS_EXTENSION_SESSION_TICKET,
                                     &epriv);
    if (ret < 0) {
        return 0;
    }
    priv = epriv;

    if (!priv->session_ticket_enable)
        return 0;

    if (session->security_parameters.entity == GNUTLS_SERVER) {
        struct ticket_st ticket;
        const uint8_t *encrypted_state;

        /* The client requested a new session ticket. */
        if (data_size == 0) {
            priv->session_ticket_renew = 1;
            return 0;
        }

        /* Format:
         *  Key name
         *  IV
         *  data length
         *  encrypted data
         *  MAC
         */
        DECR_LEN(data_size, KEY_NAME_SIZE);
        memcpy(ticket.key_name, data, KEY_NAME_SIZE);
        data += KEY_NAME_SIZE;

        /* If the key name of the ticket does not match the one that we
           hold, issue a new ticket. */
        if (memcmp
                (ticket.key_name, &priv->key[NAME_POS],
                 KEY_NAME_SIZE)) {
            priv->session_ticket_renew = 1;
            return 0;
        }

        DECR_LEN(data_size, IV_SIZE);
        memcpy(ticket.IV, data, IV_SIZE);
        data += IV_SIZE;

        DECR_LEN(data_size, 2);
        ticket.encrypted_state_len = _gnutls_read_uint16(data);
        data += 2;

        encrypted_state = data;

        DECR_LEN(data_size, ticket.encrypted_state_len);
        data += ticket.encrypted_state_len;

        DECR_LEN(data_size, MAC_SIZE);
        memcpy(ticket.mac, data, MAC_SIZE);

        ticket.encrypted_state =
            gnutls_malloc(ticket.encrypted_state_len);
        if (!ticket.encrypted_state) {
            gnutls_assert();
            return GNUTLS_E_MEMORY_ERROR;
        }
        memcpy(ticket.encrypted_state, encrypted_state,
               ticket.encrypted_state_len);

        ret = decrypt_ticket(session, priv, &ticket);

        gnutls_free(ticket.encrypted_state);
        ticket.encrypted_state = NULL;

        if (ret < 0) {
            priv->session_ticket_renew = 1;
            return 0;
        }
    } else {		/* Client */

        if (data_size == 0) {
            priv->session_ticket_renew = 1;
            return 0;
        }
    }

    return 0;
}
예제 #6
0
static int
proc_dhe_server_kx (gnutls_session_t session, opaque * data,
		    size_t _data_size)
{
  int sigsize;
  opaque *sigdata;
  gnutls_datum_t vparams, signature;
  int ret;
  cert_auth_info_t info = _gnutls_get_auth_info (session);
  ssize_t data_size = _data_size;
  gnutls_cert peer_cert;
  gnutls_sign_algorithm_t sign_algo = GNUTLS_SIGN_UNKNOWN;
  gnutls_protocol_t ver = gnutls_protocol_get_version (session);

  if (info == NULL || info->ncerts == 0)
    {
      gnutls_assert ();
      /* we need this in order to get peer's certificate */
      return GNUTLS_E_INTERNAL_ERROR;
    }

  ret = _gnutls_proc_dh_common_server_kx (session, data, _data_size, 0);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  /* VERIFY SIGNATURE */

  vparams.size = ret;
  vparams.data = data;

  sigdata = &data[vparams.size];
  if (_gnutls_version_has_selectable_sighash (ver))
    {
      sign_algorithm_st aid;

      DECR_LEN (data_size, 1);
      aid.hash_algorithm = *sigdata++;
      DECR_LEN (data_size, 1);
      aid.sign_algorithm = *sigdata++;
      sign_algo = _gnutls_tls_aid_to_sign (&aid);
      if (sign_algo == GNUTLS_SIGN_UNKNOWN)
	{
	  gnutls_assert ();
	  return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
	}
    }
  DECR_LEN (data_size, 2);
  sigsize = _gnutls_read_uint16 (sigdata);
  sigdata += 2;

  DECR_LEN (data_size, sigsize);
  signature.data = sigdata;
  signature.size = sigsize;

  if ((ret =
       _gnutls_get_auth_info_gcert (&peer_cert,
				    session->security_parameters.cert_type,
				    info, CERT_NO_COPY)) < 0)
    {
      gnutls_assert ();
      return ret;
    }

  ret =
    _gnutls_handshake_verify_data (session, &peer_cert, &vparams, &signature,
				   sign_algo);

  _gnutls_gcert_deinit (&peer_cert);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  return ret;
}
예제 #7
0
static int
unpack_ticket(gnutls_session_t session, gnutls_datum_t *packed, tls13_ticket_st *data)
{
	uint32_t age_add, lifetime;
	struct timespec creation_time;
	uint8_t resumption_master_secret[MAX_HASH_SIZE];
	size_t resumption_master_secret_size;
	uint8_t nonce[UINT8_MAX];
	size_t nonce_size;
	gnutls_datum_t state;
	gnutls_mac_algorithm_t kdf;
	const mac_entry_st *prf;
	uint8_t *p;
	ssize_t len;
	uint64_t v;
	int ret;

	if (unlikely(packed == NULL || data == NULL))
		return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);

	memset(data, 0, sizeof(*data));

	p = packed->data;
	len = packed->size;

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

	/* Check if the MAC ID we got is valid */
	prf = _gnutls_mac_to_entry(kdf);
	if (prf == NULL)
		return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);

	/* Read the ticket age add and the ticket lifetime */
	DECR_LEN(len, 4);
	age_add = _gnutls_read_uint32(p);
	p += 4;

	DECR_LEN(len, 4);
	lifetime = _gnutls_read_uint32(p);
	p += 4;

	/*
	 * Check if the whole ticket is large enough,
	 * and read the resumption master secret
	 */
	DECR_LEN(len, 1);
	resumption_master_secret_size = *p;
	p += 1;

	/* Check if the size of resumption_master_secret matches the PRF */
	if (resumption_master_secret_size != prf->output_size)
		return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);

	DECR_LEN(len, resumption_master_secret_size);
	memcpy(resumption_master_secret, p, resumption_master_secret_size);
	p += resumption_master_secret_size;

	/* Read the ticket nonce */
	DECR_LEN(len, 1);
	nonce_size = *p;
	p += 1;

	DECR_LEN(len, nonce_size);
	memcpy(nonce, p, nonce_size);
	p += nonce_size;

	DECR_LEN(len, 2);
	state.size = _gnutls_read_uint16(p);
	p += 2;

	DECR_LEN(len, state.size);
	state.data = p;
	p += state.size;

	DECR_LEN(len, 12);
	v = _gnutls_read_uint32(p);
	p += 4;
	creation_time.tv_sec = (v << 32) | _gnutls_read_uint32(p);
	p += 4;
	creation_time.tv_nsec = _gnutls_read_uint32(p);

	ret = _gnutls_session_unpack(session, &state);
	if (ret < 0)
		return gnutls_assert_val(ret);

	/* No errors - Now return all the data to the caller */
	data->prf = prf;
	memcpy(data->resumption_master_secret, resumption_master_secret,
	       resumption_master_secret_size);
	memcpy(data->nonce, nonce, nonce_size);
	data->nonce_size = nonce_size;
	data->age_add = age_add;
	data->lifetime = lifetime;
	memcpy(&data->creation_time, &creation_time, sizeof(struct timespec));

	return 0;
}
예제 #8
0
파일: dh_common.c 프로젝트: intgr/gnutls
/* Returns the bytes parsed */
int
_gnutls_proc_dh_common_server_kx (gnutls_session_t session,
                                  uint8_t * data, size_t _data_size)
{
  uint16_t n_Y, n_g, n_p;
  size_t _n_Y, _n_g, _n_p;
  uint8_t *data_p;
  uint8_t *data_g;
  uint8_t *data_Y;
  int i, bits, ret;
  ssize_t data_size = _data_size;

  i = 0;

  DECR_LEN (data_size, 2);
  n_p = _gnutls_read_uint16 (&data[i]);
  i += 2;

  DECR_LEN (data_size, n_p);
  data_p = &data[i];
  i += n_p;

  DECR_LEN (data_size, 2);
  n_g = _gnutls_read_uint16 (&data[i]);
  i += 2;

  DECR_LEN (data_size, n_g);
  data_g = &data[i];
  i += n_g;

  DECR_LEN (data_size, 2);
  n_Y = _gnutls_read_uint16 (&data[i]);
  i += 2;

  DECR_LEN (data_size, n_Y);
  data_Y = &data[i];
  i += n_Y;

  _n_Y = n_Y;
  _n_g = n_g;
  _n_p = n_p;

  if (_gnutls_mpi_scan_nz (&session->key->client_Y, data_Y, _n_Y) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  if (_gnutls_mpi_scan_nz (&session->key->client_g, data_g, _n_g) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }
  if (_gnutls_mpi_scan_nz (&session->key->client_p, data_p, _n_p) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  bits = _gnutls_dh_get_allowed_prime_bits (session);
  if (bits < 0)
    {
      gnutls_assert ();
      return bits;
    }

  if (_gnutls_mpi_get_nbits (session->key->client_p) < (size_t) bits)
    {
      /* the prime used by the peer is not acceptable
       */
      gnutls_assert ();
      return GNUTLS_E_DH_PRIME_UNACCEPTABLE;
    }

  _gnutls_dh_set_group (session, session->key->client_g,
                        session->key->client_p);
  _gnutls_dh_set_peer_public (session, session->key->client_Y);

  ret = n_Y + n_p + n_g + 6;

  return ret;
}
예제 #9
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, opaque * data,
			      int datalen)
{
  uint16_t session_id_len = 0;
  int pos = 0;
  int ret = 0;
  uint16_t sizeOfSuites;
  gnutls_protocol_t version;
  opaque rnd[TLS_RANDOM_SIZE];
  int len = datalen;
  int err;
  uint16_t challenge;
  opaque session_id[TLS_MAX_SESSION_ID_SIZE];
  gnutls_protocol_t ver;

  /* we only want to get here once - only in client hello */
  session->internals.v2_hello = 0;

  DECR_LEN (len, 2);

  _gnutls_handshake_log
    ("HSK[%x]: 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]);

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

  /* if we do not support that version  
   */
  if (_gnutls_version_is_supported (session, version) == 0)
    {
      ver = _gnutls_version_lowest (session);
    }
  else
    {
      ver = version;
    }

  _gnutls_set_current_version (session, ver);

  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 > TLS_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 > TLS_RANDOM_SIZE)
    {
      gnutls_assert ();
      return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
    }

  /* 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.
					 current_cipher_suite),
       &err) == NULL && err != 0)
    {
      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.
			     current_cipher_suite));
  if (session->internals.auth_struct == NULL)
    {

      _gnutls_handshake_log
	("HSK[%x]: 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, TLS_RANDOM_SIZE);

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

  _gnutls_set_client_random (session, rnd);

  /* generate server random value */

  _gnutls_tls_create_random (rnd);
  _gnutls_set_server_random (session, rnd);

  session->security_parameters.timestamp = 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,
	      TLS_RANDOM_SIZE);
      memcpy (session->internals.resumed_security_parameters.
	      client_random, session->security_parameters.client_random,
	      TLS_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;
    }

  session->internals.compression_method = GNUTLS_COMP_NULL;

  return 0;
}
예제 #10
0
int
_gnutls_proc_rsa_client_kx (gnutls_session_t session, opaque * data,
			    size_t _data_size)
{
  gnutls_datum_t plaintext;
  gnutls_datum_t ciphertext;
  int ret, dsize;
  bigint_t *params;
  int params_len;
  int randomize_key = 0;
  ssize_t data_size = _data_size;

  if (gnutls_protocol_get_version (session) == GNUTLS_SSL3)
    {
      /* SSL 3.0 
       */
      ciphertext.data = data;
      ciphertext.size = data_size;
    }
  else
    {
      /* TLS 1.0
       */
      DECR_LEN (data_size, 2);
      ciphertext.data = &data[2];
      dsize = _gnutls_read_uint16 (data);

      if (dsize != data_size)
	{
	  gnutls_assert ();
	  return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
	}
      ciphertext.size = dsize;
    }

  ret = _gnutls_get_private_rsa_params (session, &params, &params_len);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  ret = _gnutls_pkcs1_rsa_decrypt (&plaintext, &ciphertext, params, params_len, 2);	/* btype==2 */

  if (ret < 0 || plaintext.size != GNUTLS_MASTER_SIZE)
    {
      /* In case decryption fails then don't inform
       * the peer. Just use a random key. (in order to avoid
       * attack against pkcs-1 formating).
       */
      gnutls_assert ();
      _gnutls_x509_log ("auth_rsa: Possible PKCS #1 format attack\n");
      randomize_key = 1;
    }
  else
    {
      /* If the secret was properly formatted, then
       * check the version number.
       */
      if (_gnutls_get_adv_version_major (session) != plaintext.data[0]
	  || _gnutls_get_adv_version_minor (session) != plaintext.data[1])
	{
	  /* No error is returned here, if the version number check
	   * fails. We proceed normally.
	   * That is to defend against the attack described in the paper
	   * "Attacking RSA-based sessions in SSL/TLS" by Vlastimil Klima,
	   * Ondej Pokorny and Tomas Rosa.
	   */
	  gnutls_assert ();
	  _gnutls_x509_log
	    ("auth_rsa: Possible PKCS #1 version check format attack\n");
	}
    }

  if (randomize_key != 0)
    {
      session->key->key.size = GNUTLS_MASTER_SIZE;
      session->key->key.data = gnutls_malloc (session->key->key.size);
      if (session->key->key.data == NULL)
	{
	  gnutls_assert ();
	  return GNUTLS_E_MEMORY_ERROR;
	}

      /* we do not need strong random numbers here.
       */
      ret = _gnutls_rnd (GNUTLS_RND_NONCE, session->key->key.data,
			 session->key->key.size);
      if (ret < 0)
	{
	  gnutls_assert ();
	  return ret;
	}

    }
  else
    {
      session->key->key.data = plaintext.data;
      session->key->key.size = plaintext.size;
    }

  /* This is here to avoid the version check attack
   * discussed above.
   */
  session->key->key.data[0] = _gnutls_get_adv_version_major (session);
  session->key->key.data[1] = _gnutls_get_adv_version_minor (session);

  return 0;
}
예제 #11
0
파일: srp.c 프로젝트: Distrotech/gnutls
/* receive the key exchange message ( n, g, s, B) 
 */
int
_gnutls_proc_srp_server_kx(gnutls_session_t session, uint8_t * data,
			   size_t _data_size)
{
	uint8_t n_s;
	uint16_t n_g, n_n, n_b;
	size_t _n_g, _n_n, _n_b;
	const uint8_t *data_n;
	const uint8_t *data_g;
	const uint8_t *data_s;
	const uint8_t *data_b;
	int i, ret;
	uint8_t hd[SRP_MAX_HASH_SIZE];
	char *username, *password;
	ssize_t data_size = _data_size;
	gnutls_srp_client_credentials_t cred;
	extension_priv_data_t epriv;
	srp_ext_st *priv;

	ret =
	    _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_SRP,
					 &epriv);
	if (ret < 0) {
		gnutls_assert();
		return GNUTLS_E_UNKNOWN_SRP_USERNAME;
	}
	priv = epriv.ptr;

	cred = (gnutls_srp_client_credentials_t)
	    _gnutls_get_cred(session, GNUTLS_CRD_SRP);

	if (cred == NULL) {
		gnutls_assert();
		return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
	}

	if (priv->username == NULL) {
		username = cred->username;
		password = cred->password;
	} else {
		username = priv->username;
		password = priv->password;
	}

	if (username == NULL || password == NULL) {
		gnutls_assert();
		return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
	}

	i = 0;

	/* Read N 
	 */
	DECR_LEN(data_size, 2);
	n_n = _gnutls_read_uint16(&data[i]);
	i += 2;

	DECR_LEN(data_size, n_n);
	data_n = &data[i];
	i += n_n;

	/* Read G 
	 */
	DECR_LEN(data_size, 2);
	n_g = _gnutls_read_uint16(&data[i]);
	i += 2;

	DECR_LEN(data_size, n_g);
	data_g = &data[i];
	i += n_g;

	/* Read salt 
	 */
	DECR_LEN(data_size, 1);
	n_s = data[i];
	i += 1;

	DECR_LEN(data_size, n_s);
	data_s = &data[i];
	i += n_s;

	/* Read B 
	 */
	DECR_LEN(data_size, 2);
	n_b = _gnutls_read_uint16(&data[i]);
	i += 2;

	DECR_LEN(data_size, n_b);
	data_b = &data[i];
	i += n_b;

	_n_g = n_g;
	_n_n = n_n;
	_n_b = n_b;

	if (_gnutls_mpi_init_scan_nz(&N, data_n, _n_n) != 0) {
		gnutls_assert();
		return GNUTLS_E_MPI_SCAN_FAILED;
	}

	if (_gnutls_mpi_init_scan_nz(&G, data_g, _n_g) != 0) {
		gnutls_assert();
		return GNUTLS_E_MPI_SCAN_FAILED;
	}

	if (_gnutls_mpi_init_scan_nz(&B, data_b, _n_b) != 0) {
		gnutls_assert();
		return GNUTLS_E_MPI_SCAN_FAILED;
	}


	/* Check if the g and n are from the SRP
	 * draft. Otherwise check if N is a prime and G
	 * a generator.
	 */
	if ((ret = check_g_n(data_g, _n_g, data_n, _n_n)) < 0) {
		_gnutls_audit_log(session,
				  "SRP group parameters are not in the white list. Checking validity.\n");
		if ((ret = group_check_g_n(session, G, N)) < 0) {
			gnutls_assert();
			return ret;
		}
	}

	/* Checks if b % n == 0
	 */
	if ((ret = check_param_mod_n(B, N, 0)) < 0) {
		gnutls_assert();
		return ret;
	}


	/* generate x = SHA(s | SHA(U | ":" | p))
	 * (or the equivalent using bcrypt)
	 */
	if ((ret =
	     _gnutls_calc_srp_x(username, password, (uint8_t *) data_s,
				n_s, &_n_g, hd)) < 0) {
		gnutls_assert();
		return ret;
	}

	if (_gnutls_mpi_init_scan_nz(&session->key.x, hd, _n_g) != 0) {
		gnutls_assert();
		return GNUTLS_E_MPI_SCAN_FAILED;
	}


	return i;		/* return the processed data
				 * needed in auth_srp_rsa.
				 */
}
예제 #12
0
파일: srp.c 프로젝트: Distrotech/gnutls
/* just read A and put it to session */
int
_gnutls_proc_srp_client_kx(gnutls_session_t session, uint8_t * data,
			   size_t _data_size)
{
	size_t _n_A;
	ssize_t data_size = _data_size;
	int ret;

	DECR_LEN(data_size, 2);
	_n_A = _gnutls_read_uint16(&data[0]);

	DECR_LEN(data_size, _n_A);
	if (_gnutls_mpi_init_scan_nz(&A, &data[2], _n_A) || A == NULL) {
		gnutls_assert();
		return GNUTLS_E_MPI_SCAN_FAILED;
	}

	_gnutls_mpi_log("SRP A: ", A);
	_gnutls_mpi_log("SRP B: ", B);

	/* Checks if A % n == 0.
	 */
	if ((ret = check_param_mod_n(A, N, 1)) < 0) {
		gnutls_assert();
		return ret;
	}

	/* Start the SRP calculations.
	 * - Calculate u 
	 */
	session->key.u = _gnutls_calc_srp_u(A, B, N);
	if (session->key.u == NULL) {
		gnutls_assert();
		return GNUTLS_E_MEMORY_ERROR;
	}

	_gnutls_mpi_log("SRP U: ", session->key.u);

	/* S = (A * v^u) ^ b % N 
	 */
	S = _gnutls_calc_srp_S1(A, _b, session->key.u, V, N);
	if (S == NULL) {
		gnutls_assert();
		return GNUTLS_E_MEMORY_ERROR;
	}

	_gnutls_mpi_log("SRP S: ", S);

	_gnutls_mpi_release(&A);
	zrelease_temp_mpi_key(&_b);
	zrelease_temp_mpi_key(&V);
	zrelease_temp_mpi_key(&session->key.u);
	zrelease_temp_mpi_key(&B);

	ret = _gnutls_mpi_dprint(session->key.srp_key, &session->key.key);
	zrelease_temp_mpi_key(&S);

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

	return 0;
}
예제 #13
0
int _gnutls_recv_new_session_ticket(gnutls_session_t session)
{
    uint8_t *p;
    int data_size;
    gnutls_buffer_st buf;
    uint16_t ticket_len;
    int ret;
    session_ticket_ext_st *priv = NULL;
    extension_priv_data_t epriv;

    ret =
        _gnutls_ext_get_session_data(session,
                                     GNUTLS_EXTENSION_SESSION_TICKET,
                                     &epriv);
    if (ret < 0) {
        gnutls_assert();
        return 0;
    }
    priv = epriv;

    if (!priv->session_ticket_renew)
        return 0;

    /* This is the last flight and peer cannot be sure
     * we have received it unless we notify him. So we
     * wait for a message and retransmit if needed. */
    if (IS_DTLS(session) && !_dtls_is_async(session) &&
            (gnutls_record_check_pending(session) +
             record_check_unprocessed(session)) == 0) {
        ret = _dtls_wait_and_retransmit(session);
        if (ret < 0)
            return gnutls_assert_val(ret);
    }

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

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

    DECR_LENGTH_COM(data_size, 4, ret =
                        GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
                    goto error);
    /* skip over lifetime hint */
    p += 4;

    DECR_LENGTH_COM(data_size, 2, ret =
                        GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
                    goto error);
    ticket_len = _gnutls_read_uint16(p);
    p += 2;

    DECR_LENGTH_COM(data_size, ticket_len, ret =
                        GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
                    goto error);
    priv->session_ticket =
        gnutls_realloc_fast(priv->session_ticket, ticket_len);
    if (!priv->session_ticket) {
        gnutls_assert();
        ret = GNUTLS_E_MEMORY_ERROR;
        goto error;
    }
    memcpy(priv->session_ticket, p, ticket_len);
    priv->session_ticket_len = ticket_len;

    /* Discard the current session ID.  (RFC5077 3.4) */
    ret =
        _gnutls_generate_session_id(session->security_parameters.
                                    session_id,
                                    &session->security_parameters.
                                    session_id_size);
    if (ret < 0) {
        gnutls_assert();
        gnutls_free(priv->session_ticket);
        priv->session_ticket = NULL;
        ret = GNUTLS_E_INTERNAL_ERROR;
        goto error;
    }
    ret = 0;

error:
    _gnutls_buffer_clear(&buf);

    return ret;
}
예제 #14
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.ptr = priv;
		_gnutls_ext_set_session_data(session,
					     GNUTLS_EXTENSION_SERVER_NAME,
					     epriv);

	}

	return 0;
}
예제 #15
0
static int
parse_handshake_header (gnutls_session_t session, mbuffer_st* bufel, gnutls_handshake_description_t htype, 
    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 */
  if (!IS_DTLS(session) && htype == GNUTLS_HANDSHAKE_CLIENT_HELLO &&
    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 /* TLS 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 = 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 was received. Length %d[%d], frag offset %d, frag length: %d, sequence: %d\n",
                         session, _gnutls_handshake2str (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;
}
예제 #16
0
/* Checks the record headers and returns the length, version and
 * content type.
 */
static void
record_read_headers(gnutls_session_t session,
		    uint8_t headers[MAX_RECORD_HEADER_SIZE],
		    content_type_t type,
		    gnutls_handshake_description_t htype,
		    struct tls_record_st *record)
{

	/* Read the first two bytes to determine if this is a 
	 * version 2 message 
	 */

	if (htype == GNUTLS_HANDSHAKE_CLIENT_HELLO
	    && type == GNUTLS_HANDSHAKE && headers[0] > 127
	    && !(IS_DTLS(session))) {

		/* if msb set and expecting handshake message
		 * it should be SSL 2 hello 
		 */
		record->version[0] = 3;	/* assume SSL 3.0 */
		record->version[1] = 0;

		record->length = (((headers[0] & 0x7f) << 8)) | headers[1];

		/* SSL 2.0 headers */
		record->header_size = record->packet_size = 2;
		record->type = GNUTLS_HANDSHAKE;	/* we accept only v2 client hello
							 */

		/* in order to assist the handshake protocol.
		 * V2 compatibility is a mess.
		 */
		record->v2 = 1;
		record->epoch = 0;
		memset(&record->sequence, 0, sizeof(record->sequence));

		_gnutls_record_log
		    ("REC[%p]: SSL 2.0 %s packet received. Length: %d\n",
		     session, _gnutls_packet2str(record->type),
		     record->length);

	} else {
		/* dtls version 1.0 and TLS version 1.x */
		record->v2 = 0;

		record->type = headers[0];
		record->version[0] = headers[1];
		record->version[1] = headers[2];

		if (IS_DTLS(session)) {
			memcpy(record->sequence.i, &headers[3], 8);
			record->length = _gnutls_read_uint16(&headers[11]);
			record->epoch =
			    _gnutls_read_uint16(record->sequence.i);
		} else {
			memset(&record->sequence, 0,
			       sizeof(record->sequence));
			record->length = _gnutls_read_uint16(&headers[3]);
			record->epoch = 0;
		}

		_gnutls_record_log
		    ("REC[%p]: SSL %d.%d %s packet received. Epoch %d, length: %d\n",
		     session, (int) record->version[0],
		     (int) record->version[1],
		     _gnutls_packet2str(record->type), (int) record->epoch,
		     record->length);

	}

	record->packet_size += record->length;
}
예제 #17
0
static int
proc_srp_cert_server_kx (gnutls_session_t session, opaque * data,
			 size_t _data_size)
{
  ssize_t ret;
  int sigsize;
  gnutls_datum_t vparams, signature;
  ssize_t data_size;
  cert_auth_info_t info;
  gnutls_cert peer_cert;
  opaque *p;

  ret = _gnutls_proc_srp_server_kx (session, data, _data_size);
  if (ret < 0)
    return ret;

  data_size = _data_size - ret;

  info = _gnutls_get_auth_info (session);
  if (info == NULL || info->ncerts == 0)
    {
      gnutls_assert ();
      /* we need this in order to get peer's certificate */
      return GNUTLS_E_INTERNAL_ERROR;
    }

  /* VERIFY SIGNATURE */

  vparams.size = ret;		/* all the data minus the signature */
  vparams.data = data;

  p = &data[vparams.size];

  DECR_LEN (data_size, 2);
  sigsize = _gnutls_read_uint16 (p);

  DECR_LEN (data_size, sigsize);
  signature.data = &p[2];
  signature.size = sigsize;

  ret =
    _gnutls_get_auth_info_gcert (&peer_cert,
				 session->security_parameters.cert_type,
				 info, CERT_NO_COPY);

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

  ret = _gnutls_verify_sig_params (session, &peer_cert, &vparams, &signature);

  _gnutls_gcert_deinit (&peer_cert);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  return 0;
}
예제 #18
0
파일: dh_common.c 프로젝트: intgr/gnutls
int
_gnutls_proc_dh_common_client_kx (gnutls_session_t session,
                                  uint8_t * data, size_t _data_size,
                                  bigint_t g, bigint_t p,
                                  gnutls_datum_t* psk_key)
{
  uint16_t n_Y;
  size_t _n_Y;
  int ret;
  ssize_t data_size = _data_size;


  DECR_LEN (data_size, 2);
  n_Y = _gnutls_read_uint16 (&data[0]);
  _n_Y = n_Y;

  DECR_LEN (data_size, n_Y);
  if (_gnutls_mpi_scan_nz (&session->key->client_Y, &data[2], _n_Y))
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  _gnutls_dh_set_peer_public (session, session->key->client_Y);

  ret =
    gnutls_calc_dh_key (&session->key->KEY, session->key->client_Y, session->key->dh_secret, p);
  if (ret < 0)
    return gnutls_assert_val(ret);

  _gnutls_mpi_release (&session->key->client_Y);
  _gnutls_mpi_release (&session->key->dh_secret);


  if (psk_key == NULL)
    {
      ret = _gnutls_mpi_dprint (session->key->KEY, &session->key->key);
    }
  else                          /* In DHE_PSK the key is set differently */
    {
      gnutls_datum_t tmp_dh_key;
      ret = _gnutls_mpi_dprint (session->key->KEY, &tmp_dh_key);
      if (ret < 0)
        {
          gnutls_assert ();
          return ret;
        }

      ret = _gnutls_set_psk_session_key (session, psk_key, &tmp_dh_key);
      _gnutls_free_datum (&tmp_dh_key);

    }

  _gnutls_mpi_release (&session->key->KEY);

  if (ret < 0)
    {
      return ret;
    }

  return 0;
}
예제 #19
0
파일: psk.c 프로젝트: GostCrypt/GnuTLS
/* just read the username from the client key exchange.
 */
static int
_gnutls_proc_psk_client_kx(gnutls_session_t session, uint8_t * data,
			   size_t _data_size)
{
	ssize_t data_size = _data_size;
	int ret;
	gnutls_datum_t username, psk_key;
	gnutls_psk_server_credentials_t cred;
	psk_auth_info_t info;

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

	if (cred == NULL) {
		gnutls_assert();
		return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
	}

	if ((ret =
	     _gnutls_auth_info_set(session, GNUTLS_CRD_PSK,
				   sizeof(psk_auth_info_st), 1)) < 0) {
		gnutls_assert();
		return ret;
	}

	DECR_LEN(data_size, 2);
	username.size = _gnutls_read_uint16(&data[0]);

	DECR_LEN(data_size, username.size);

	username.data = &data[2];


	/* copy the username to the auth info structures
	 */
	info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
	if (info == NULL) {
		gnutls_assert();
		return GNUTLS_E_INTERNAL_ERROR;
	}

	if (username.size > MAX_USERNAME_SIZE) {
		gnutls_assert();
		return GNUTLS_E_ILLEGAL_SRP_USERNAME;
	}

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

	ret =
	    _gnutls_psk_pwd_find_entry(session, info->username, &psk_key);
	if (ret < 0)
		return gnutls_assert_val(ret);

	ret = _gnutls_set_psk_session_key(session, &psk_key, NULL);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	ret = 0;

      error:
	_gnutls_free_key_datum(&psk_key);

	return ret;
}