Ejemplo n.º 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;
}
Ejemplo n.º 2
0
/**
 * gnutls_auth_client_get_type:
 * @session: is a #gnutls_session_t structure.
 *
 * Returns the type of credentials that were used for client authentication.
 * The returned information is to be used to distinguish the function used
 * to access authentication data.
 *
 * Returns: The type of credentials for the client authentication
 *   schema, a #gnutls_credentials_type_t type.
 **/
gnutls_credentials_type_t
gnutls_auth_client_get_type(gnutls_session_t session)
{
	return
	    _gnutls_map_kx_get_cred(_gnutls_cipher_suite_get_kx_algo
				    (session->security_parameters.
				     cipher_suite), 0);
}
Ejemplo n.º 3
0
/* This function reads the RSA parameters from the private key
 */
static int
_gnutls_get_private_rsa_params (gnutls_session_t session,
				bigint_t ** params, int *params_size)
{
  int bits;
  gnutls_certificate_credentials_t cred;
  gnutls_rsa_params_t rsa_params;

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

  if (session->internals.selected_cert_list == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
    }

  bits =
    _gnutls_mpi_get_nbits (session->internals.selected_cert_list[0].
			   params[0]);

  if (_gnutls_cipher_suite_get_kx_algo
      (&session->security_parameters.current_cipher_suite)
      == GNUTLS_KX_RSA_EXPORT && bits > 512)
    {

      rsa_params =
	_gnutls_certificate_get_rsa_params (cred->rsa_params,
					    cred->params_func, session);
      /* EXPORT case: */
      if (rsa_params == NULL)
	{
	  gnutls_assert ();
	  return GNUTLS_E_NO_TEMPORARY_RSA_PARAMS;
	}

      /* In the export case, we do use temporary RSA params
       * of 512 bits size. The params in the certificate are
       * used to sign this temporary stuff.
       */
      *params_size = RSA_PRIVATE_PARAMS;
      *params = rsa_params->params;

      return 0;
    }

  /* non export cipher suites. */

  *params_size = session->internals.selected_key->params_size;
  *params = session->internals.selected_key->params;

  return 0;
}
Ejemplo n.º 4
0
/**
 * gnutls_kx_get:
 * @session: is a #gnutls_session_t type.
 *
 * Get currently used key exchange algorithm.
 *
 * Returns: the key exchange algorithm used in the last handshake, a
 *   #gnutls_kx_algorithm_t value.
 **/
gnutls_kx_algorithm_t gnutls_kx_get(gnutls_session_t session)
{
	if (session->internals.handshake_in_progress) {
		/* This allows early call during handshake */
		return _gnutls_cipher_suite_get_kx_algo(session->security_parameters.cipher_suite);
	} else {
		return session->security_parameters.kx_algorithm;
	}
}
Ejemplo n.º 5
0
int
_gnutls_gen_dh_common_client_kx_int(gnutls_session_t session,
				    gnutls_buffer_st * data,
				    gnutls_datum_t * pskkey)
{
	int ret;
	gnutls_pk_params_st peer_pub;
	gnutls_datum_t tmp_dh_key = {NULL, 0};
	
	gnutls_pk_params_init(&peer_pub);

	ret =
	    _gnutls_pk_generate_keys(GNUTLS_PK_DH, 0,
				     &session->key.dh_params, 1);
	if (ret < 0)
		return gnutls_assert_val(ret);

	_gnutls_dh_set_secret_bits(session, _gnutls_mpi_get_nbits(session->key.dh_params.params[DH_X]));

	ret = _gnutls_buffer_append_mpi(data, 16, session->key.dh_params.params[DH_Y], 0);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}
	
	peer_pub.params[DH_Y] = session->key.client_Y;

	/* calculate the key after calculating the message */
	ret = _gnutls_pk_derive(GNUTLS_PK_DH, &tmp_dh_key, &session->key.dh_params, &peer_pub);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	if (_gnutls_cipher_suite_get_kx_algo
	    (session->security_parameters.cipher_suite)
	    != GNUTLS_KX_DHE_PSK) {
		session->key.key.data = tmp_dh_key.data;
		session->key.key.size = tmp_dh_key.size;
	} else {		/* In DHE_PSK the key is set differently */
		ret =
		    _gnutls_set_psk_session_key(session, pskkey,
						&tmp_dh_key);
		_gnutls_free_temp_key_datum(&tmp_dh_key);
	}

	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	ret = data->length;

 error:
	gnutls_pk_params_clear(&session->key.dh_params);
	return ret;
}
Ejemplo n.º 6
0
/**
 * gnutls_auth_get_type:
 * @session: is a #gnutls_session_t structure.
 *
 * Returns type of credentials for the current authentication schema.
 * The returned information is to be used to distinguish the function used
 * to access authentication data.
 *
 * Eg. for CERTIFICATE ciphersuites (key exchange algorithms:
 * %GNUTLS_KX_RSA, %GNUTLS_KX_DHE_RSA), the same function are to be
 * used to access the authentication data.
 *
 * Returns: The type of credentials for the current authentication
 *   schema, a #gnutls_credentials_type_t type.
 **/
gnutls_credentials_type_t gnutls_auth_get_type(gnutls_session_t session)
{
/* This is not the credentials we must set, but the authentication data
 * we get by the peer, so it should be reversed.
 */
	int server =
	    session->security_parameters.entity == GNUTLS_SERVER ? 0 : 1;

	return
	    _gnutls_map_kx_get_cred(_gnutls_cipher_suite_get_kx_algo
				    (session->security_parameters.
				     cipher_suite), server);
}
Ejemplo n.º 7
0
/* This function reads the RSA parameters from the private key
 */
static int
_gnutls_get_private_rsa_params (gnutls_session_t session,
                                gnutls_pk_params_st** params)
{
  int ret;
  gnutls_certificate_credentials_t cred;
  gnutls_rsa_params_t rsa_params;

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

  if (session->internals.selected_cert_list == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
    }

  ret = _gnutls_pubkey_is_over_rsa_512(session->internals.selected_cert_list[0].pubkey);

  if (_gnutls_cipher_suite_get_kx_algo
      (session->security_parameters.cipher_suite)
      != GNUTLS_KX_RSA_EXPORT || ret < 0)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  rsa_params =
    _gnutls_certificate_get_rsa_params (cred->rsa_params,
                                        cred->params_func, session);
  /* EXPORT case: */
  if (rsa_params == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_NO_TEMPORARY_RSA_PARAMS;
    }

  /* In the export case, we do use temporary RSA params
   * of 512 bits size. The params in the certificate are
   * used to sign this temporary stuff.
   */
  *params = &rsa_params->params;

  return 0;
}
Ejemplo n.º 8
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;
}
Ejemplo n.º 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, 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;
}
Ejemplo n.º 10
0
int
_gnutls_gen_dh_common_client_kx_int (gnutls_session_t session, gnutls_buffer_st* data, gnutls_datum_t* pskkey)
{
  bigint_t x = NULL, X = NULL;
  int ret;

  ret = gnutls_calc_dh_secret (&X, &x, session->key.client_g,
                             session->key.client_p, 0);
  if (ret < 0)
    {
      gnutls_assert ();
      goto error;
    }

  _gnutls_dh_set_secret_bits (session, _gnutls_mpi_get_nbits (x));

  ret = _gnutls_buffer_append_mpi( data, 16, X, 0);
  if (ret < 0)
    {
      gnutls_assert();
      goto error;
    }

  /* calculate the key after calculating the message */
  ret =
    gnutls_calc_dh_key (&session->key.KEY, session->key.client_Y, x, session->key.client_p);
  if (ret < 0)
    {
      gnutls_assert();
      goto error;
    }

  /* THESE SHOULD BE DISCARDED */
  _gnutls_mpi_release (&session->key.client_Y);
  _gnutls_mpi_release (&session->key.client_p);
  _gnutls_mpi_release (&session->key.client_g);

  if (_gnutls_cipher_suite_get_kx_algo
      (session->security_parameters.cipher_suite)
      != GNUTLS_KX_DHE_PSK)
    {
      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 ();
          goto error;
        }

      ret = _gnutls_set_psk_session_key (session, pskkey, &tmp_dh_key);
      _gnutls_free_datum (&tmp_dh_key);
    }

  _gnutls_mpi_release (&session->key.KEY);

  if (ret < 0)
    {
      gnutls_assert ();
      goto error;
    }

  ret = data->length;

error:
  _gnutls_mpi_release (&x);
  _gnutls_mpi_release (&X);
  return ret;
}
Ejemplo n.º 11
0
int
_gnutls_proc_dh_common_client_kx (gnutls_session_t session,
				  opaque * data, size_t _data_size,
				  mpi_t g, mpi_t p)
{
  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);

  session->key->KEY =
    gnutls_calc_dh_key (session->key->client_Y, session->key->dh_secret, p);

  if (session->key->KEY == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

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


  if (_gnutls_cipher_suite_get_kx_algo
      (&session->security_parameters.current_cipher_suite)
      != GNUTLS_KX_DHE_PSK)
    {
      ret = _gnutls_mpi_dprint (&session->key->key, session->key->KEY);
    }
  else				/* In DHE_PSK the key is set differently */
    {
      gnutls_datum tmp_dh_key;
      ret = _gnutls_mpi_dprint (&tmp_dh_key, session->key->KEY);
      if (ret < 0)
	{
	  gnutls_assert ();
	  return ret;
	}

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

    }

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

  if (ret < 0)
    {
      return ret;
    }

  return 0;
}
Ejemplo n.º 12
0
int
_gnutls_gen_dh_common_client_kx (gnutls_session_t session, opaque ** data)
{
  mpi_t x = NULL, X = NULL;
  size_t n_X;
  int ret;

  *data = NULL;

  X = gnutls_calc_dh_secret (&x, session->key->client_g,
			     session->key->client_p);
  if (X == NULL || x == NULL)
    {
      gnutls_assert ();
      ret = GNUTLS_E_MEMORY_ERROR;
      goto error;
    }

  _gnutls_dh_set_secret_bits (session, _gnutls_mpi_get_nbits (x));

  _gnutls_mpi_print (NULL, &n_X, X);
  (*data) = gnutls_malloc (n_X + 2);
  if (*data == NULL)
    {
      ret = GNUTLS_E_MEMORY_ERROR;
      goto error;
    }

  _gnutls_mpi_print (&(*data)[2], &n_X, X);
  _gnutls_mpi_release (&X);

  _gnutls_write_uint16 (n_X, &(*data)[0]);

  /* calculate the key after calculating the message */
  session->key->KEY =
    gnutls_calc_dh_key (session->key->client_Y, x, session->key->client_p);

  _gnutls_mpi_release (&x);
  if (session->key->KEY == NULL)
    {
      gnutls_assert ();
      ret = GNUTLS_E_MEMORY_ERROR;
      goto error;
    }

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

  /* THESE SHOULD BE DISCARDED */
  _gnutls_mpi_release (&session->key->client_Y);
  _gnutls_mpi_release (&session->key->client_p);
  _gnutls_mpi_release (&session->key->client_g);

  if (_gnutls_cipher_suite_get_kx_algo
      (&session->security_parameters.current_cipher_suite)
      != GNUTLS_KX_DHE_PSK)
    {
      ret = _gnutls_mpi_dprint (&session->key->key, session->key->KEY);
    }
  else				/* In DHE_PSK the key is set differently */
    {
      gnutls_datum tmp_dh_key;
      ret = _gnutls_mpi_dprint (&tmp_dh_key, session->key->KEY);
      if (ret < 0)
	{
	  gnutls_assert ();
	  goto error;
	}

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

    }

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

  if (ret < 0)
    {
      gnutls_assert ();
      goto error;
    }

  return n_X + 2;

error:
  _gnutls_mpi_release (&x);
  _gnutls_mpi_release (&X);
  gnutls_free (*data);
  *data = NULL;
  return ret;
}
Ejemplo n.º 13
0
/* Initializes the write connection session
 * (write encrypted data)
 */
int
_gnutls_write_connection_state_init (gnutls_session_t session)
{
  int mac_size;
  int rc;

  _gnutls_uint64zero (session->connection_state.write_sequence_number);

/* Update internals from CipherSuite selected.
 * If we are resuming just copy the connection session
 */
  if (session->internals.resumed == RESUME_FALSE)
    {
      rc = _gnutls_set_write_cipher (session,
				     _gnutls_cipher_suite_get_cipher_algo
				     (&session->security_parameters.
				      current_cipher_suite));
      if (rc < 0)
	return rc;
      rc = _gnutls_set_write_mac (session,
				  _gnutls_cipher_suite_get_mac_algo
				  (&session->security_parameters.
				   current_cipher_suite));
      if (rc < 0)
	return rc;

      rc = _gnutls_set_kx (session,
			   _gnutls_cipher_suite_get_kx_algo
			   (&session->security_parameters.
			    current_cipher_suite));
      if (rc < 0)
	return rc;

      rc = _gnutls_set_write_compression (session,
					  session->internals.
					  compression_method);
      if (rc < 0)
	return rc;
    }
  else
    {				/* RESUME_TRUE */
      _gnutls_cpy_write_security_parameters (&session->
					     security_parameters,
					     &session->
					     internals.
					     resumed_security_parameters);
    }

  rc = _gnutls_set_write_keys (session);
  if (rc < 0)
    return rc;

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

  if (_gnutls_compression_is_ok
      (session->security_parameters.write_compression_algorithm) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM;
    }

  if (_gnutls_mac_is_ok
      (session->security_parameters.write_mac_algorithm) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }



  /* Free all the previous keys/ sessions etc.
   */
  if (session->connection_state.write_mac_secret.data != NULL)
    _gnutls_free_datum (&session->connection_state.write_mac_secret);

  if (session->connection_state.write_cipher_state != NULL)
    _gnutls_cipher_deinit (session->connection_state.write_cipher_state);

  if (session->connection_state.write_compression_state != NULL)
    _gnutls_comp_deinit (session->connection_state.
			 write_compression_state, 0);

  mac_size =
    _gnutls_hash_get_algo_len (session->security_parameters.
			       write_mac_algorithm);

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

  switch (session->security_parameters.entity)
    {
    case GNUTLS_SERVER:
      /* initialize cipher session
       */
      session->connection_state.write_cipher_state =
	_gnutls_cipher_init (session->security_parameters.
			     write_bulk_cipher_algorithm,
			     &session->cipher_specs.
			     server_write_key,
			     &session->cipher_specs.server_write_IV);

      if (session->connection_state.write_cipher_state ==
	  GNUTLS_CIPHER_FAILED
	  && session->security_parameters.
	  write_bulk_cipher_algorithm != GNUTLS_CIPHER_NULL)
	{
	  gnutls_assert ();
	  return GNUTLS_E_INTERNAL_ERROR;
	}


      /* copy mac secrets from cipherspecs, to connection
       * session.
       */
      if (mac_size > 0)
	{
	  if (_gnutls_sset_datum (&session->connection_state.
				  write_mac_secret,
				  session->cipher_specs.
				  server_write_mac_secret.data,
				  session->cipher_specs.
				  server_write_mac_secret.size) < 0)
	    {
	      gnutls_assert ();
	      return GNUTLS_E_MEMORY_ERROR;
	    }

	}


      break;

    case GNUTLS_CLIENT:
      session->connection_state.write_cipher_state =
	_gnutls_cipher_init (session->security_parameters.
			     write_bulk_cipher_algorithm,
			     &session->cipher_specs.
			     client_write_key,
			     &session->cipher_specs.client_write_IV);

      if (session->connection_state.write_cipher_state ==
	  GNUTLS_CIPHER_FAILED
	  && session->security_parameters.
	  write_bulk_cipher_algorithm != GNUTLS_CIPHER_NULL)
	{
	  gnutls_assert ();
	  return GNUTLS_E_INTERNAL_ERROR;
	}

      /* copy mac secret to connection session
       */
      if (mac_size > 0)
	{
	  if (_gnutls_sset_datum (&session->connection_state.
				  write_mac_secret,
				  session->cipher_specs.
				  client_write_mac_secret.data,
				  session->cipher_specs.
				  client_write_mac_secret.size) < 0)
	    {
	      gnutls_assert ();
	      return GNUTLS_E_MEMORY_ERROR;
	    }
	}

      break;

    default:
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }


  session->connection_state.write_compression_state =
    _gnutls_comp_init (session->security_parameters.
		       write_compression_algorithm, 0);

  if (session->connection_state.write_compression_state == GNUTLS_COMP_FAILED)
    {
      gnutls_assert ();
      return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM;
    }

  return 0;
}
Ejemplo n.º 14
0
/* This function reads the RSA parameters from peer's certificate;
 */
static int
_gnutls_get_public_rsa_params (gnutls_session_t session,
			       bigint_t params[MAX_PUBLIC_PARAMS_SIZE],
			       int *params_len)
{
  int ret;
  cert_auth_info_t info;
  gnutls_cert peer_cert;
  int i;

  /* normal non export case */

  info = _gnutls_get_auth_info (session);

  if (info == NULL || info->ncerts == 0)
    {
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }

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

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


  /* EXPORT case: */
  if (_gnutls_cipher_suite_get_kx_algo
      (&session->security_parameters.current_cipher_suite) ==
      GNUTLS_KX_RSA_EXPORT
      && _gnutls_mpi_get_nbits (peer_cert.params[0]) > 512)
    {

      _gnutls_gcert_deinit (&peer_cert);

      if (session->key->rsa[0] == NULL || session->key->rsa[1] == NULL)
	{
	  gnutls_assert ();
	  return GNUTLS_E_INTERNAL_ERROR;
	}

      if (*params_len < 2)
	{
	  gnutls_assert ();
	  return GNUTLS_E_INTERNAL_ERROR;
	}
      *params_len = 2;
      for (i = 0; i < *params_len; i++)
	{
	  params[i] = _gnutls_mpi_copy (session->key->rsa[i]);
	}

      return 0;
    }

  /* end of export case */

  if (*params_len < peer_cert.params_size)
    {
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }
  *params_len = peer_cert.params_size;

  for (i = 0; i < *params_len; i++)
    {
      params[i] = _gnutls_mpi_copy (peer_cert.params[i]);
    }
  _gnutls_gcert_deinit (&peer_cert);

  return 0;
}
Ejemplo n.º 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, 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;
}