Пример #1
0
static int
gen_ecdhe_server_kx(gnutls_session_t session, gnutls_buffer_st * data)
{
	int ret = 0;
	gnutls_certificate_credentials_t cred;

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

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

	ret =
	    _gnutls_ecdh_common_print_server_kx(session, data,
						_gnutls_session_ecc_curve_get
						(session));
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	/* Generate the signature. */
	return _gnutls_gen_dhe_signature(session, data, data->data,
					 data->length);
}
Пример #2
0
/* Generates the PSK server key exchange
 *
 * struct {
 *     select (KeyExchangeAlgorithm) {
 *         // other cases for rsa, diffie_hellman, etc.
 *         case psk:  // NEW
 *             uint8_t psk_identity_hint<0..2^16-1>;
 *     };
 * } ServerKeyExchange;
 *
 */
int
_gnutls_gen_psk_server_kx (gnutls_session_t session, gnutls_buffer_st* data)
{
  gnutls_psk_server_credentials_t cred;
  gnutls_datum_t hint;

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

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

  /* Abort sending this message if there is no PSK identity hint. */
  if (cred->hint == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INT_RET_0;
    }

  hint.data = (uint8_t*)cred->hint;
  hint.size = strlen (cred->hint);

  return _gnutls_buffer_append_data_prefix(data, 16, hint.data, hint.size);
}
Пример #3
0
static int
proc_dhe_client_kx (gnutls_session_t session, opaque * data,
                    size_t _data_size)
{
  gnutls_certificate_credentials_t cred;
  int ret;
  bigint_t p, g;
  const bigint_t *mpis;
  gnutls_dh_params_t dh_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;
    }

  dh_params =
    _gnutls_get_dh_params (cred->dh_params, cred->params_func, session);
  mpis = _gnutls_dh_params_to_mpi (dh_params);
  if (mpis == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_NO_TEMPORARY_DH_PARAMS;
    }

  p = mpis[0];
  g = mpis[1];

  ret = _gnutls_proc_dh_common_client_kx (session, data, _data_size, g, p);

  return ret;

}
Пример #4
0
/* just read the username from the client key exchange.
 */
int
_gnutls_proc_psk_client_kx (gnutls_session_t session, opaque * data,
                            size_t _data_size)
{
  ssize_t data_size = _data_size;
  int ret;
  gnutls_datum_t username;
  gnutls_psk_server_credentials_t cred;
  psk_auth_info_t info;

  cred = (gnutls_psk_server_credentials_t)
    _gnutls_get_cred (session->key, GNUTLS_CRD_PSK, NULL);

  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);

  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_set_psk_session_key (session, NULL);
  if (ret < 0)
    {
      gnutls_assert ();
      goto error;
    }

  ret = 0;

error:
  return ret;
}
Пример #5
0
/* Generates the PSK client key exchange
 *
 * 
 * struct {
 *    select (KeyExchangeAlgorithm) {
 *       uint8_t psk_identity<0..2^16-1>;
 *    } exchange_keys;
 * } ClientKeyExchange;
 *
 */
int
_gnutls_gen_psk_client_kx(gnutls_session_t session,
			  gnutls_buffer_st * data)
{
	int ret, free;
	gnutls_datum_t username = {NULL, 0};
	gnutls_datum_t key;
	gnutls_psk_client_credentials_t cred;
	psk_auth_info_t info;

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

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

	info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
	if (info == NULL) {
		gnutls_assert();
		return GNUTLS_E_INTERNAL_ERROR;
	}

	ret = _gnutls_find_psk_key(session, cred, &username, &key, &free);
	if (ret < 0)
		return gnutls_assert_val(ret);

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

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

	if (username.size > sizeof(info->username)-1) {
		gnutls_assert();
		ret = GNUTLS_E_ILLEGAL_SRP_USERNAME;
		goto cleanup;
	}

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


      cleanup:
	if (free) {
		gnutls_free(username.data);
		_gnutls_free_temp_key_datum(&key);
	}

	return ret;
}
Пример #6
0
/*-
  * _gnutls_openpgp_crt_verify_peers - This function returns the peer's certificate status
  * @session: is a gnutls session
  *
  * This function will try to verify the peer's certificate and return its status (TRUSTED, INVALID etc.). 
  * Returns a negative error code in case of an error, or GNUTLS_E_NO_CERTIFICATE_FOUND if no certificate was sent.
  *
  -*/
int
_gnutls_openpgp_crt_verify_peers (gnutls_session_t session,
				   unsigned int *status)
{
  cert_auth_info_t info;
  gnutls_certificate_credentials_t cred;
  int peer_certificate_list_size, ret;

  CHECK_AUTH (GNUTLS_CRD_CERTIFICATE, GNUTLS_E_INVALID_REQUEST);

  info = _gnutls_get_auth_info (session);
  if (info == NULL)
    return GNUTLS_E_INVALID_REQUEST;

  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 (info->raw_certificate_list == NULL || info->ncerts == 0)
    {
      gnutls_assert ();
      return GNUTLS_E_NO_CERTIFICATE_FOUND;
    }

  /* generate a list of gnutls_certs based on the auth info
   * raw certs.
   */
  peer_certificate_list_size = info->ncerts;

  if (peer_certificate_list_size != 1)
    {
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }

  /* Verify certificate 
   */
  if (_E_gnutls_openpgp_verify_key == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INIT_LIBEXTRA;
    }
  ret =
    _E_gnutls_openpgp_verify_key (cred, &info->raw_certificate_list[0],
				  peer_certificate_list_size, status);

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

  return 0;
}
Пример #7
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;
}
Пример #8
0
/* 
 * This returns a pointer to the linked list. Don't
 * free that!!!
 */
const void *_gnutls_get_kx_cred(gnutls_session_t session,
				gnutls_kx_algorithm_t algo)
{
	int server =
	    session->security_parameters.entity == GNUTLS_SERVER ? 1 : 0;

	return _gnutls_get_cred(session,
				_gnutls_map_kx_get_cred(algo, server));
}
Пример #9
0
static int
gen_dhe_server_kx(gnutls_session_t session, gnutls_buffer_st * data)
{
	bigint_t g, p;
	const bigint_t *mpis;
	int ret = 0;
	gnutls_certificate_credentials_t cred;
	gnutls_dh_params_t dh_params;

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


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

	dh_params =
	    _gnutls_get_dh_params(cred->dh_params, cred->params_func,
				  session);
	mpis = _gnutls_dh_params_to_mpi(dh_params);
	if (mpis == NULL) {
		gnutls_assert();
		return GNUTLS_E_NO_TEMPORARY_DH_PARAMS;
	}

	p = mpis[0];
	g = mpis[1];

	_gnutls_dh_set_group(session, g, p);

	ret = _gnutls_set_dh_pk_params(session, g, p, dh_params->q_bits);
	if (ret < 0)
		return gnutls_assert_val(ret);

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

	/* Generate the signature. */
	return _gnutls_gen_dhe_signature(session, data, data->data,
					 data->length);
}
Пример #10
0
/* just read the hint from the server key exchange.
 */
static int
_gnutls_proc_psk_server_kx(gnutls_session_t session, uint8_t * data,
			   size_t _data_size)
{
	ssize_t data_size = _data_size;
	int ret;
	gnutls_datum_t hint;
	gnutls_psk_client_credentials_t cred;
	psk_auth_info_t info;

	cred = (gnutls_psk_client_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_LENGTH_RET(data_size, 2, 0);
	hint.size = _gnutls_read_uint16(&data[0]);

	DECR_LEN(data_size, hint.size);

	hint.data = &data[2];

	/* copy the hint 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 (hint.size > sizeof(info->hint)-1) {
		gnutls_assert();
		return GNUTLS_E_ILLEGAL_SRP_USERNAME;
	}

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

	ret = 0;

	return ret;
}
Пример #11
0
static int
gen_psk_client_kx (gnutls_session_t session, opaque ** data)
{
  int ret;
  opaque *tmp_data = NULL;
  int data_size, tmp_data_size;
  gnutls_psk_client_credentials_t cred;

  cred = (gnutls_psk_client_credentials_t)
    _gnutls_get_cred (session->key, GNUTLS_CRD_PSK, NULL);

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

  if (cred->username.data == NULL || cred->key.data == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
    }

  /* The PSK key is set in there */
  ret = _gnutls_gen_dh_common_client_kx (session, &tmp_data);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  tmp_data_size = ret;
  data_size = tmp_data_size + cred->username.size + 2;

  (*data) = gnutls_malloc (data_size);
  if ((*data) == NULL)
    {
      gnutls_assert ();
      ret = GNUTLS_E_MEMORY_ERROR;
      goto error;
    }

  _gnutls_write_datum16 (*data, cred->username);
  memcpy (&(*data)[cred->username.size + 2], tmp_data, tmp_data_size);

  ret = data_size;

error:
  gnutls_free (tmp_data);
  return ret;

}
Пример #12
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;
}
Пример #13
0
static int
gen_dhe_psk_server_kx(gnutls_session_t session, gnutls_buffer_st * data)
{
	bigint_t g, p;
	const bigint_t *mpis;
	int ret;
	gnutls_dh_params_t dh_params;
	gnutls_psk_server_credentials_t cred;

	cred = (gnutls_psk_server_credentials_t)
	    _gnutls_get_cred(session, GNUTLS_CRD_PSK, NULL);
	if (cred == NULL) {
		gnutls_assert();
		return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
	}

	dh_params =
	    _gnutls_get_dh_params(cred->dh_params, cred->params_func,
				  session);
	mpis = _gnutls_dh_params_to_mpi(dh_params);
	if (mpis == NULL) {
		gnutls_assert();
		return GNUTLS_E_NO_TEMPORARY_DH_PARAMS;
	}

	p = mpis[0];
	g = mpis[1];

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

	_gnutls_dh_set_group(session, g, p);

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

	ret =
	    _gnutls_dh_common_print_server_kx(session, g, p,
					      dh_params->q_bits, data);
	if (ret < 0)
		gnutls_assert();

	return ret;
}
Пример #14
0
/* Check if the given certificate type is supported.
 * This means that it is enabled by the priority functions,
 * and a matching certificate exists.
 */
int
_gnutls_session_cert_type_supported (gnutls_session_t session,
                                     gnutls_certificate_type_t cert_type)
{
  unsigned i;
  unsigned cert_found = 0;
  gnutls_certificate_credentials_t cred;

  if (session->security_parameters.entity == GNUTLS_SERVER)
    {
      cred = (gnutls_certificate_credentials_t)
        _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL);

      if (cred == NULL)
        return GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;

      if (cred->server_get_cert_callback == NULL
          && cred->get_cert_callback == NULL)
        {
          for (i = 0; i < cred->ncerts; i++)
            {
              if (cred->cert_list[i][0].type == cert_type)
                {
                  cert_found = 1;
                  break;
                }
            }

          if (cert_found == 0)
            /* no certificate is of that type.
             */
            return GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
        }
    }

  if (session->internals.priorities.cert_type.algorithms == 0
      && cert_type == DEFAULT_CERT_TYPE)
    return 0;

  for (i = 0; i < session->internals.priorities.cert_type.algorithms; i++)
    {
      if (session->internals.priorities.cert_type.priority[i] == cert_type)
        {
          return 0;             /* ok */
        }
    }

  return GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
}
Пример #15
0
/**
 * gnutls_credentials_get:
 * @session: is a #gnutls_session_t structure.
 * @type: is the type of the credentials to return
 * @cred: will contain the pointer to the credentials structure.
 *
 * Returns the previously provided credentials structures.
 *
 * For %GNUTLS_CRD_ANON, @cred will be
 * #gnutls_anon_client_credentials_t in case of a client.  In case of
 * a server it should be #gnutls_anon_server_credentials_t.
 *
 * For %GNUTLS_CRD_SRP, @cred will be #gnutls_srp_client_credentials_t
 * in case of a client, and #gnutls_srp_server_credentials_t, in case
 * of a server.
 *
 * For %GNUTLS_CRD_CERTIFICATE, @cred will be
 * #gnutls_certificate_credentials_t.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
 *   otherwise a negative error code is returned.
 **/
int
gnutls_credentials_get(gnutls_session_t session,
		       gnutls_credentials_type_t type, void **cred)
{
const void *_cred;

	_cred = _gnutls_get_cred(session, type);
	if (_cred == NULL)
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

	if (cred)
		*cred = (void*)_cred;

	return 0;
}
Пример #16
0
static int
gen_anon_server_kx (gnutls_session_t session, gnutls_buffer_st* data)
{
  bigint_t g, p;
  const bigint_t *mpis;
  int ret;
  gnutls_dh_params_t dh_params;
  gnutls_anon_server_credentials_t cred;

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

  dh_params =
    _gnutls_get_dh_params (cred->dh_params, cred->params_func, session);
  mpis = _gnutls_dh_params_to_mpi (dh_params);
  if (mpis == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_NO_TEMPORARY_DH_PARAMS;
    }

  p = mpis[0];
  g = mpis[1];

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

  _gnutls_dh_set_group (session, g, p);

  ret = _gnutls_dh_common_print_server_kx (session, g, p, data, 0);
  if (ret < 0)
    {
      gnutls_assert ();
    }

  return ret;
}
Пример #17
0
/**
 * gnutls_certificate_get_ours:
 * @session: is a gnutls session
 *
 * Gets the certificate as sent to the peer in the last handshake.
 * The certificate is in raw (DER) format.  No certificate
 * list is being returned. Only the first certificate.
 *
 * Returns: a pointer to a #gnutls_datum_t containing our
 *   certificate, or %NULL in case of an error or if no certificate
 *   was used.
 **/
const gnutls_datum_t *gnutls_certificate_get_ours(gnutls_session_t session)
{
	gnutls_certificate_credentials_t cred;

	CHECK_AUTH(GNUTLS_CRD_CERTIFICATE, NULL);

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

	if (session->internals.selected_cert_list == NULL)
		return NULL;

	return &session->internals.selected_cert_list[0].cert;
}
Пример #18
0
static int
proc_ecdhe_client_kx(gnutls_session_t session,
		     uint8_t * data, size_t _data_size)
{
	gnutls_certificate_credentials_t cred;

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

	return _gnutls_proc_ecdh_common_client_kx(session, data,
						  _data_size,
						  _gnutls_session_ecc_curve_get
						  (session), NULL);
}
Пример #19
0
static int
gen_ecdhe_psk_client_kx(gnutls_session_t session, gnutls_buffer_st * data)
{
	int ret, free;
	gnutls_psk_client_credentials_t cred;
	gnutls_datum_t username, key;

	cred = (gnutls_psk_client_credentials_t)
	    _gnutls_get_cred(session, GNUTLS_CRD_PSK, NULL);

	if (cred == NULL)
		return
		    gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);

	ret = _gnutls_find_psk_key(session, cred, &username, &key, &free);
	if (ret < 0)
		return gnutls_assert_val(ret);

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

	/* The PSK key is set in there */
	ret = _gnutls_gen_ecdh_common_client_kx_int(session, data, &key);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret = data->length;

      cleanup:
	if (free) {
		_gnutls_free_datum(&username);
		_gnutls_free_datum(&key);
	}

	return ret;
}
Пример #20
0
/* Generates the PSK client key exchange
 *
 * 
 * struct {
 *    select (KeyExchangeAlgorithm) {
 *       uint8_t psk_identity<0..2^16-1>;
 *    } exchange_keys;
 * } ClientKeyExchange;
 *
 */
int
_gnutls_gen_psk_client_kx (gnutls_session_t session, gnutls_buffer_st* data)
{
  int ret, free;
  gnutls_datum_t username;
  gnutls_datum_t key;
  gnutls_psk_client_credentials_t cred;

  cred = (gnutls_psk_client_credentials_t)
    _gnutls_get_cred (session, GNUTLS_CRD_PSK, NULL);

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

  ret = _gnutls_find_psk_key( session, cred, &username, &key, &free);
  if (ret < 0)
    return gnutls_assert_val(ret);

  ret = _gnutls_set_psk_session_key (session, &key, NULL);
  if (ret < 0)
    {
      gnutls_assert();
      goto cleanup;
    }
  
  ret = _gnutls_buffer_append_data_prefix(data, 16, username.data, username.size);
  if (ret < 0)
    {
      gnutls_assert();
    }

cleanup:
  if (free) 
    {
      gnutls_free(username.data);
      gnutls_free(key.data);
    }
  
  return ret;
}
Пример #21
0
static int
gen_dhe_server_kx(gnutls_session_t session, gnutls_buffer_st * data)
{
	int ret = 0;
	gnutls_certificate_credentials_t cred;
	unsigned sig_pos;

	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;
	}

	ret =
	    _gnutls_figure_dh_params(session, cred->dh_params, cred->params_func, cred->dh_sec_param);
	if (ret < 0) {
		return gnutls_assert_val(ret);
	}

	sig_pos = data->length;

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

	/* Generate the signature. */
	return _gnutls_gen_dhe_signature(session, data, &data->data[sig_pos],
					 data->length-sig_pos);
}
Пример #22
0
static int
proc_anon_client_kx (gnutls_session_t session, opaque * data,
		     size_t _data_size)
{
  gnutls_anon_server_credentials_t cred;
  int bits;
  int ret;
  mpi_t p, g;
  gnutls_dh_params_t dh_params;
  const mpi_t *mpis;

  bits = _gnutls_dh_get_allowed_prime_bits (session);

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

  dh_params =
    _gnutls_get_dh_params (cred->dh_params, cred->params_func, session);
  mpis = _gnutls_dh_params_to_mpi (dh_params);
  if (mpis == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_NO_TEMPORARY_DH_PARAMS;
    }

  p = mpis[0];
  g = mpis[1];

  ret = _gnutls_proc_dh_common_client_kx (session, data, _data_size, g, p);

  return ret;

}
Пример #23
0
/* Generates the PSK server key exchange
 *
 * struct {
 *     select (KeyExchangeAlgorithm) {
 *         // other cases for rsa, diffie_hellman, etc.
 *         case psk:  // NEW
 *             opaque psk_identity_hint<0..2^16-1>;
 *     };
 * } ServerKeyExchange;
 *
 */
int
_gnutls_gen_psk_server_kx (gnutls_session_t session, opaque ** data)
{
  gnutls_psk_server_credentials_t cred;
  gnutls_datum_t hint;

  cred = (gnutls_psk_server_credentials_t)
    _gnutls_get_cred (session->key, GNUTLS_CRD_PSK, NULL);

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

  /* Abort sending this message if there is no PSK identity hint. */
  if (cred->hint == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INT_RET_0;
    }

  hint.data = cred->hint;
  hint.size = strlen (cred->hint);

  (*data) = gnutls_malloc (2 + hint.size);
  if ((*data) == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  _gnutls_write_datum16 (*data, hint);

  return hint.size + 2;
}
Пример #24
0
static int
server_send(gnutls_session_t session,
	    gnutls_buffer_st * extdata, status_request_ext_st * priv)
{
	int ret;
	gnutls_certificate_credentials_t cred;

	cred = (gnutls_certificate_credentials_t)
	    _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE, NULL);
	if (cred == NULL)	/* no certificate authentication */
		return gnutls_assert_val(0);

	if (cred->ocsp_func == NULL)
		return gnutls_assert_val(GNUTLS_E_SUCCESS);

	ret =
	    cred->ocsp_func(session, cred->ocsp_func_ptr, &priv->response);
	if (ret == GNUTLS_E_NO_CERTIFICATE_STATUS)
		return 0;
	else if (ret < 0)
		return gnutls_assert_val(ret);

	return GNUTLS_E_INT_RET_0;
}
Пример #25
0
/*
 * Return values for this function:
 *  -  0 : Not applicable.
 *  - >0 : Ok. Return size of extension data.
 *  - GNUTLS_E_INT_RET_0 : Size of extension data is zero.
 *  - <0 : There's been an error.
 *
 * In the client, generates the PskIdentity and PskBinderEntry messages.
 *
 *      PskIdentity identities<7..2^16-1>;
 *      PskBinderEntry binders<33..2^16-1>;
 *
 *      struct {
 *          opaque identity<1..2^16-1>;
 *          uint32 obfuscated_ticket_age;
 *      } PskIdentity;
 *
 *      opaque PskBinderEntry<32..255>;
 *
 * The server sends the selected identity, which is a zero-based index
 * of the PSKs offered by the client:
 *
 *      struct {
 *          uint16 selected_identity;
 *      } PreSharedKeyExtension;
 */
static int _gnutls_psk_send_params(gnutls_session_t session,
				   gnutls_buffer_t extdata)
{
	gnutls_psk_client_credentials_t cred = NULL;
	const version_entry_st *vers;

	if (session->security_parameters.entity == GNUTLS_CLIENT) {
		vers = _gnutls_version_max(session);

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

		if (session->internals.hsk_flags & HSK_PSK_KE_MODES_SENT) {
			cred = (gnutls_psk_client_credentials_t)
					_gnutls_get_cred(session, GNUTLS_CRD_PSK);
		}

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

		return client_send_params(session, extdata, cred);
	} else {
		vers = get_version(session);

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

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

		if (session->internals.hsk_flags & HSK_PSK_KE_MODES_RECEIVED)
			return server_send_params(session, extdata);
		else
			return 0;
	}
}
Пример #26
0
static int
_gnutls_ia_server_handshake (gnutls_session_t session)
{
  gnutls_ia_apptype_t msg_type;
  ssize_t len;
  char buf[1024];
  int ret;
  const struct gnutls_ia_server_credentials_st *cred =
    _gnutls_get_cred (session->key, GNUTLS_CRD_IA, NULL);

  if (cred == NULL)
    return GNUTLS_E_INTERNAL_ERROR;

  do
    {
      char *avp;
      size_t avplen;

      len = gnutls_ia_recv (session, buf, sizeof (buf));
      if (len == GNUTLS_E_WARNING_IA_IPHF_RECEIVED ||
	  len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED)
	{
	  ret = gnutls_ia_verify_endphase (session, buf);
	  if (ret < 0)
	    return ret;
	}

      if (len == GNUTLS_E_WARNING_IA_IPHF_RECEIVED)
	continue;
      else if (len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED)
	break;

      if (len < 0)
	return len;

      avp = NULL;
      avplen = 0;

      ret = cred->avp_func (session, cred->avp_ptr, buf, len, &avp, &avplen);
      if (ret < 0)
	{
	  int tmpret;
	  tmpret = gnutls_alert_send (session, GNUTLS_AL_FATAL,
				      GNUTLS_A_INNER_APPLICATION_FAILURE);
	  if (tmpret < 0)
	    gnutls_assert ();
	  return ret;
	}

      msg_type = ret;

      if (msg_type != GNUTLS_IA_APPLICATION_PAYLOAD)
	{
	  ret = gnutls_ia_endphase_send (session, msg_type ==
					 GNUTLS_IA_FINAL_PHASE_FINISHED);
	  if (ret < 0)
	    return ret;
	}
      else
	{
	  len = gnutls_ia_send (session, avp, avplen);
	  gnutls_free (avp);
	  if (len < 0)
	    return len;
	}
    }
  while (1);

  return 0;
}
Пример #27
0
static int
_gnutls_ia_client_handshake (gnutls_session_t session)
{
  char *buf = NULL;
  size_t buflen = 0;
  char tmp[1024];		/* XXX */
  ssize_t len;
  int ret;
  const struct gnutls_ia_client_credentials_st *cred =
    _gnutls_get_cred (session->key, GNUTLS_CRD_IA, NULL);

  if (cred == NULL)
    return GNUTLS_E_INTERNAL_ERROR;

  while (1)
    {
      char *avp;
      size_t avplen;

      ret = cred->avp_func (session, cred->avp_ptr,
			    buf, buflen, &avp, &avplen);
      if (ret)
	{
	  int tmpret;
	  tmpret = gnutls_alert_send (session, GNUTLS_AL_FATAL,
				      GNUTLS_A_INNER_APPLICATION_FAILURE);
	  if (tmpret < 0)
	    gnutls_assert ();
	  return ret;
	}

      len = gnutls_ia_send (session, avp, avplen);
      gnutls_free (avp);
      if (len < 0)
	return len;

      len = gnutls_ia_recv (session, tmp, sizeof (tmp));
      if (len == GNUTLS_E_WARNING_IA_IPHF_RECEIVED ||
	  len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED)
	{
	  ret = gnutls_ia_verify_endphase (session, tmp);
	  if (ret < 0)
	    return ret;

	  ret = gnutls_ia_endphase_send
	    (session, len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED);
	  if (ret < 0)
	    return ret;
	}

      if (len == GNUTLS_E_WARNING_IA_IPHF_RECEIVED)
	{
	  buf = NULL;
	  buflen = 0;
	  continue;
	}
      else if (len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED)
	break;

      if (len < 0)
	return len;

      buflen = len;
      buf = tmp;
    }

  return 0;
}
Пример #28
0
static int
gen_dhe_server_kx (gnutls_session_t session, opaque ** data)
{
  bigint_t g, p;
  const bigint_t *mpis;
  int ret = 0, data_size;
  gnutls_cert *apr_cert_list;
  gnutls_privkey_t apr_pkey;
  int apr_cert_list_length;
  gnutls_datum_t signature = { NULL, 0 }, ddata;
  gnutls_certificate_credentials_t cred;
  gnutls_dh_params_t dh_params;
  gnutls_sign_algorithm_t sign_algo;
  gnutls_protocol_t ver = gnutls_protocol_get_version (session);

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

  /* find the appropriate certificate */
  if ((ret =
       _gnutls_get_selected_cert (session, &apr_cert_list,
                                  &apr_cert_list_length, &apr_pkey)) < 0)
    {
      gnutls_assert ();
      return ret;
    }

  dh_params =
    _gnutls_get_dh_params (cred->dh_params, cred->params_func, session);
  mpis = _gnutls_dh_params_to_mpi (dh_params);
  if (mpis == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_NO_TEMPORARY_DH_PARAMS;
    }

  p = mpis[0];
  g = mpis[1];

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

  _gnutls_dh_set_group (session, g, p);

  ret = _gnutls_dh_common_print_server_kx (session, g, p, data, 0);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }
  data_size = ret;

  /* Generate the signature. */

  ddata.data = *data;
  ddata.size = data_size;

  if (apr_cert_list_length > 0)
    {
      if ((ret =
           _gnutls_handshake_sign_data (session, &apr_cert_list[0],
                                        apr_pkey, &ddata, &signature,
                                        &sign_algo)) < 0)
        {
          gnutls_assert ();
          goto cleanup;
        }
    }
  else
    {
      gnutls_assert ();
      ret = data_size;         /* do not put a signature - ILLEGAL! */
      goto cleanup;
    }

  *data = gnutls_realloc_fast (*data, data_size + signature.size + 4);
  if (*data == NULL)
    {
      gnutls_assert ();
      ret = GNUTLS_E_MEMORY_ERROR;
      goto cleanup;
    }

  if (_gnutls_version_has_selectable_sighash (ver))
    {
      const sign_algorithm_st *aid;

      if (sign_algo == GNUTLS_SIGN_UNKNOWN)
        {
          ret = GNUTLS_E_UNKNOWN_ALGORITHM;
          goto cleanup;
        }

      aid = _gnutls_sign_to_tls_aid (sign_algo);
      if (aid == NULL)
        {
          gnutls_assert();
          ret = GNUTLS_E_UNKNOWN_ALGORITHM;
          goto cleanup;
        }
      
      (*data)[data_size++] = aid->hash_algorithm;
      (*data)[data_size++] = aid->sign_algorithm;
    }

  _gnutls_write_datum16 (&(*data)[data_size], signature);
  data_size += signature.size + 2;

  _gnutls_free_datum (&signature);

  return data_size;

cleanup:
  _gnutls_free_datum (&signature);
  gnutls_free(*data);
  return ret;

}
Пример #29
0
/* returns data_size or a negative number on failure
 */
int
_gnutls_inner_application_send_params (gnutls_session_t session,
				       opaque * data, size_t data_size)
{
  tls_ext_st *ext = &session->security_parameters.extensions;

  /* Set ext->gnutls_ia_enable depending on whether we have a TLS/IA
     credential in the session. */

  if (session->security_parameters.entity == GNUTLS_CLIENT)
    {
      gnutls_ia_client_credentials_t cred = (gnutls_ia_client_credentials_t)
	_gnutls_get_cred (session->key, GNUTLS_CRD_IA, NULL);

      if (cred)
	ext->gnutls_ia_enable = 1;
    }
  else
    {
      gnutls_ia_server_credentials_t cred = (gnutls_ia_server_credentials_t)
	_gnutls_get_cred (session->key, GNUTLS_CRD_IA, NULL);

      if (cred)
	ext->gnutls_ia_enable = 1;
    }

  /* If we don't want gnutls_ia locally, or we are a server and the
   * client doesn't want it, don't advertise TLS/IA support at all, as
   * required. */

  if (!ext->gnutls_ia_enable)
    return 0;

  if (session->security_parameters.entity == GNUTLS_SERVER &&
      !ext->gnutls_ia_peer_enable)
    return 0;

  /* We'll advertise. Check if there's room in the hello buffer. */

  if (data_size < 1)
    {
      gnutls_assert ();
      return GNUTLS_E_SHORT_MEMORY_BUFFER;
    }

  /* default: require new application phase */

  *data = YES;

  if (session->security_parameters.entity == GNUTLS_CLIENT)
    {

      /* Client: value follows local setting */

      if (ext->gnutls_ia_allowskip)
	*data = NO;
    }
  else
    {

      /* Server: value follows local setting and client's setting, but only
       * if we are resuming.
       *
       * XXX Can server test for resumption at this stage?
       *
       * Ai! It seems that read_client_hello only calls parse_extensions if
       * we're NOT resuming! That would make us automatically violate the IA
       * draft; if we're resuming, we must first learn what the client wants
       * -- IA or no IA -- and then prepare our response. Right now we'll
       * always skip IA on resumption, because recv_ext isn't even called
       * to record the peer's support for IA at all. Simon? */

      if (ext->gnutls_ia_allowskip &&
	  ext->gnutls_ia_peer_allowskip &&
	  session->internals.resumed == RESUME_TRUE)
	*data = NO;
    }

  return 1;
}
Пример #30
0
/* receive the key exchange message ( n, g, s, B) 
 */
int
_gnutls_proc_srp_server_kx (gnutls_session_t session, opaque * data,
			    size_t _data_size)
{
  uint8_t n_s;
  uint16_t n_g, n_n, n_b;
  size_t _n_s, _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;
  opaque hd[SRP_MAX_HASH_SIZE];
  char *username, *password;
  ssize_t data_size = _data_size;
  gnutls_srp_client_credentials_t cred;

  cred = (gnutls_srp_client_credentials_t)
    _gnutls_get_cred (session->key, GNUTLS_CRD_SRP, NULL);

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

  if (session->internals.srp_username == NULL)
    {
      username = cred->username;
      password = cred->password;
    }
  else
    {
      username = session->internals.srp_username;
      password = session->internals.srp_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_s = n_s;
  _n_g = n_g;
  _n_n = n_n;
  _n_b = n_b;

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

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

  if (_gnutls_mpi_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_x509_log ("Checking the SRP group parameters.\n");
      if ((ret = group_check_g_n (G, N)) < 0)
	{
	  gnutls_assert ();
	  return ret;
	}
    }

  /* Checks if b % n == 0
   */
  if ((ret = check_b_mod_n (B, N)) < 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, (opaque *) data_s, n_s,
			   &_n_g, hd)) < 0)
    {
      gnutls_assert ();
      return ret;
    }

  if (_gnutls_mpi_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.
				 */
}