_select_client_cert (gnutls_session_t session,
                     uint8_t * _data, size_t _data_size,
                     gnutls_pk_algorithm_t * pk_algos, int pk_algos_length)
{
  int result;
  int indx = -1;
  gnutls_certificate_credentials_t cred;
  uint8_t *data = _data;
  ssize_t data_size = _data_size;
  int issuers_dn_length;
  gnutls_datum_t *issuers_dn = NULL;

  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 (cred->client_get_cert_callback != NULL
      || cred->get_cert_callback != NULL || cred->get_cert_callback2 != NULL)
    {

      /* use a callback to get certificate 
       */
      if (session->security_parameters.cert_type != GNUTLS_CRT_X509)
        issuers_dn_length = 0;
      else
        {
          issuers_dn_length = get_issuers_num (session, data, data_size);
          if (issuers_dn_length < 0)
            {
              gnutls_assert ();
              return issuers_dn_length;
            }

          if (issuers_dn_length > 0)
            {
              issuers_dn =
                gnutls_malloc (sizeof (gnutls_datum_t) * issuers_dn_length);
              if (issuers_dn == NULL)
                {
                  gnutls_assert ();
                  return GNUTLS_E_MEMORY_ERROR;
                }

              result =
                get_issuers (session, issuers_dn, issuers_dn_length,
                             data, data_size);
              if (result < 0)
                {
                  gnutls_assert ();
                  goto cleanup;
                }
            }
        }

      result =
        call_get_cert_callback (session, issuers_dn, issuers_dn_length,
                                pk_algos, pk_algos_length);
      goto cleanup;

    }
  else
    {
      /* If we have no callbacks, try to guess.
       */
      result = 0;

      if (session->security_parameters.cert_type == GNUTLS_CRT_X509)
        result =
          _find_x509_cert (cred, _data, _data_size,
                           pk_algos, pk_algos_length, &indx);
#ifdef ENABLE_OPENPGP
      else if (session->security_parameters.cert_type == GNUTLS_CRT_OPENPGP)
        result = _find_openpgp_cert (cred, pk_algos, pk_algos_length, &indx);
#endif

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

      if (indx >= 0)
        {
          _gnutls_selected_certs_set (session,
                                      &cred->certs[indx].cert_list[0],
                                      cred->certs[indx].cert_list_length,
                                      cred->pkey[indx], 0);
        }
      else
        {
          _gnutls_selected_certs_set (session, NULL, 0, NULL, 0);
        }

      result = 0;
    }

cleanup:
  gnutls_free (issuers_dn);
  return result;

}
_select_client_cert (gnutls_session_t session,
                     uint8_t * _data, size_t _data_size,
                     gnutls_pk_algorithm_t * pk_algos, int pk_algos_length)
{
  int result;
  int indx = -1;
  gnutls_certificate_credentials_t cred;
  uint8_t *data = _data;
  ssize_t data_size = _data_size;
  int issuers_dn_length;
  gnutls_datum_t *issuers_dn = NULL;

  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 (cred->client_get_cert_callback != NULL
      || cred->get_cert_callback != NULL || cred->get_cert_callback2 != NULL)
    {

       
      if (session->security_parameters.cert_type != GNUTLS_CRT_X509)
        issuers_dn_length = 0;
      else
        {
          issuers_dn_length = get_issuers_num (session, data, data_size);
          if (issuers_dn_length < 0)
            {
              gnutls_assert ();
              return issuers_dn_length;
            }

          if (issuers_dn_length > 0)
            {
              issuers_dn =
                gnutls_malloc (sizeof (gnutls_datum_t) * issuers_dn_length);
              if (issuers_dn == NULL)
                {
                  gnutls_assert ();
                  return GNUTLS_E_MEMORY_ERROR;
                }

              result =
                get_issuers (session, issuers_dn, issuers_dn_length,
                             data, data_size);
              if (result < 0)
                {
                  gnutls_assert ();
                  goto cleanup;
                }
            }
        }

      result =
        call_get_cert_callback (session, issuers_dn, issuers_dn_length,
                                pk_algos, pk_algos_length);
      goto cleanup;

    }
  else
    {
       
      result = 0;

      if (session->security_parameters.cert_type == GNUTLS_CRT_X509)
        result =
          _find_x509_cert (cred, _data, _data_size,
                           pk_algos, pk_algos_length, &indx);
#ifdef ENABLE_OPENPGP
      else if (session->security_parameters.cert_type == GNUTLS_CRT_OPENPGP)
        result = _find_openpgp_cert (cred, pk_algos, pk_algos_length, &indx);
#endif

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

      if (indx >= 0)
        {
          _gnutls_selected_certs_set (session,
                                      &cred->certs[indx].cert_list[0],
                                      cred->certs[indx].cert_list_length,
                                      cred->pkey[indx], 0);
        }
      else
        {
          _gnutls_selected_certs_set (session, NULL, 0, NULL, 0);
        }

      result = 0;
    }

cleanup:
  gnutls_free (issuers_dn);
  return result;

}