Example #1
0
File: app.c Project: Juul/gnupg
/* Decrypt the data in INDATA and return the allocated result in OUTDATA.
   If a PIN is required the PINCB will be used to ask for the PIN; it
   should return the PIN in an allocated buffer and put it into PIN.  */
gpg_error_t
app_decipher (app_t app, const char *keyidstr,
              gpg_error_t (*pincb)(void*, const char *, char **),
              void *pincb_arg,
              const void *indata, size_t indatalen,
              unsigned char **outdata, size_t *outdatalen )
{
  gpg_error_t err;

  if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
    return gpg_error (GPG_ERR_INV_VALUE);
  if (!app->ref_count)
    return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
  if (!app->fnc.decipher)
    return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
  err = lock_reader (app->slot, NULL /*FIXME*/);
  if (err)
    return err;
  err = app->fnc.decipher (app, keyidstr,
                           pincb, pincb_arg,
                           indata, indatalen,
                           outdata, outdatalen);
  unlock_reader (app->slot);
  if (opt.verbose)
    log_info ("operation decipher result: %s\n", gpg_strerror (err));
  return err;
}
Example #2
0
File: app.c Project: Juul/gnupg
/* Perform the WRITEKEY operation.  */
gpg_error_t
app_writekey (app_t app, ctrl_t ctrl,
              const char *keyidstr, unsigned int flags,
              gpg_error_t (*pincb)(void*, const char *, char **),
              void *pincb_arg,
              const unsigned char *keydata, size_t keydatalen)
{
  gpg_error_t err;

  if (!app || !keyidstr || !*keyidstr || !pincb)
    return gpg_error (GPG_ERR_INV_VALUE);
  if (!app->ref_count)
    return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
  if (!app->fnc.writekey)
    return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
  err = lock_reader (app->slot, ctrl);
  if (err)
    return err;
  err = app->fnc.writekey (app, ctrl, keyidstr, flags,
                           pincb, pincb_arg, keydata, keydatalen);
  unlock_reader (app->slot);
  if (opt.verbose)
    log_info ("operation writekey result: %s\n", gpg_strerror (err));
  return err;
}
Example #3
0
File: app.c Project: Juul/gnupg
/* This may be called to tell this module about a removed or resetted card. */
void
application_notify_card_reset (int slot)
{
  app_t app;

  if (slot < 0 || slot >= DIM (lock_table))
    return;

  /* FIXME: We are ignoring any error value here.  */
  lock_reader (slot, NULL);

  /* Mark application as non-reusable.  */
  if (lock_table[slot].app)
    lock_table[slot].app->no_reuse = 1;

  /* Deallocate a saved application for that slot, so that we won't
     try to reuse it.  If there is no saved application, set a flag so
     that we won't save the current state. */
  app = lock_table[slot].last_app;

  if (app)
    {
      lock_table[slot].last_app = NULL;
      deallocate_app (app);
    }
  unlock_reader (slot);
}
Example #4
0
int gpuvm_kernel_begin(void *hostptr, unsigned idev, int flags) {
	//fprintf(stderr, "beginning kernel\n");
	// check arguments
	if(!hostptr) {
		fprintf(stderr, "gpuvm_kernel_begin: hostptr is NULL\n");
		return GPUVM_ENULL;
	}
	if(idev >= ndevs_g) {
		fprintf(stderr, "gpuvm_kernel_begin: invalid device number\n");
		return GPUVM_EARG;		
	}
	if(flags != GPUVM_READ_WRITE && flags != GPUVM_READ_ONLY) {
		fprintf(stderr, "gpuvm_kernel_begin: invalid flags\n");
		return GPUVM_EARG;
	}

	if(lock_reader())
		return GPUVM_ERROR;

	// find host array
	host_array_t *host_array = host_array_find_by_ptr(hostptr);
	if(!host_array) {
		fprintf(stderr, "gpuvm_kernel_begin: hostptr %p is not registed with "
						"GPUVM\n", hostptr);
		unlock_reader();
		return GPUVM_EHOSTPTR;
	}
	
	// copy data to device if needed
	int err;
	if(err = host_array_sync_to_device(host_array, idev, flags)) {
		unlock_reader();
		return err;
	}
	
	if(unlock_reader())
		return GPUVM_ERROR;

	return 0;
}  // gpuvm_kernel_begin
Example #5
0
File: app.c Project: Juul/gnupg
/* Free the resources associated with the application APP.  APP is
   allowed to be NULL in which case this is a no-op.  Note that we are
   using reference counting to track the users of the application and
   actually deferring the deallocation to allow for a later reuse by
   a new connection. */
void
release_application (app_t app)
{
  int slot;

  if (!app)
    return;

  if (!app->ref_count)
    log_bug ("trying to release an already released context\n");
  if (--app->ref_count)
    return;

  /* Move the reference to the application in the lock table. */
  slot = app->slot;
  /* FIXME: We are ignoring any error value.  */
  lock_reader (slot, NULL);
  if (lock_table[slot].app != app)
    {
      unlock_reader (slot);
      log_bug ("app mismatch %p/%p\n", app, lock_table[slot].app);
      deallocate_app (app);
      return;
    }

  if (lock_table[slot].last_app)
    deallocate_app (lock_table[slot].last_app);
  if (app->no_reuse)
    {
      /* If we shall not re-use the application we can't save it for
         later use. */
      deallocate_app (app);
      lock_table[slot].last_app = NULL;
    }
  else
    lock_table[slot].last_app = lock_table[slot].app;
  lock_table[slot].app = NULL;
  unlock_reader (slot);
}
Example #6
0
/** pre-unlinks the host array by synchronizing it back to host and unprotecting
		it 
		@param hostptr the address of the host array to be synchronized and
		unprotected
		@returns 0 if successful and a negative error code if not
*/
static int gpuvm_pre_unlink(void *hostptr) {
	if(lock_reader())
		return GPUVM_ERROR;

	// get the array
	host_array_t *host_array = host_array_find_by_ptr(hostptr);
	if(!host_array) {
		unlock_reader();
		fprintf(stderr, "gpuvm_pre_unlink: not a valid pointer\n");
		return GPUVM_EHOSTPTR;
	}
	
	// tap into the beginning of each array subregion, to cause readback if
	// mprotected 
	unsigned isubreg;
	int err;
	for(isubreg = 0; isubreg < host_array->nsubregs; isubreg++) {
		err += *(char*)host_array->subregs[isubreg]->range.ptr;
	}
	
	unlock_reader();
	return 0;
}  // gpuvm_pre_unlink()
Example #7
0
File: app.c Project: Juul/gnupg
/* Perform a GET CHALLENGE operation.  This fucntion is special as it
   directly accesses the card without any application specific
   wrapper. */
gpg_error_t
app_get_challenge (app_t app, size_t nbytes, unsigned char *buffer)
{
  gpg_error_t err;

  if (!app || !nbytes || !buffer)
    return gpg_error (GPG_ERR_INV_VALUE);
  if (!app->ref_count)
    return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
  err = lock_reader (app->slot, NULL /*FIXME*/);
  if (err)
    return err;
  err = iso7816_get_challenge (app->slot, nbytes, buffer);
  unlock_reader (app->slot);
  return err;
}
Example #8
0
File: app.c Project: Juul/gnupg
/* Read the certificate with id CERTID (as returned by learn_status in
   the CERTINFO status lines) and return it in the freshly allocated
   buffer put into CERT and the length of the certificate put into
   CERTLEN. */
gpg_error_t
app_readcert (app_t app, const char *certid,
              unsigned char **cert, size_t *certlen)
{
  gpg_error_t err;

  if (!app)
    return gpg_error (GPG_ERR_INV_VALUE);
  if (!app->ref_count)
    return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
  if (!app->fnc.readcert)
    return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
  err = lock_reader (app->slot, NULL/* FIXME*/);
  if (err)
    return err;
  err = app->fnc.readcert (app, certid, cert, certlen);
  unlock_reader (app->slot);
  return err;
}
Example #9
0
File: app.c Project: Juul/gnupg
/* Perform a SETATTR operation.  */
gpg_error_t
app_setattr (app_t app, const char *name,
             gpg_error_t (*pincb)(void*, const char *, char **),
             void *pincb_arg,
             const unsigned char *value, size_t valuelen)
{
  gpg_error_t err;

  if (!app || !name || !*name || !value)
    return gpg_error (GPG_ERR_INV_VALUE);
  if (!app->ref_count)
    return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
  if (!app->fnc.setattr)
    return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
  err = lock_reader (app->slot, NULL /*FIXME*/);
  if (err)
    return err;
  err = app->fnc.setattr (app, name, pincb, pincb_arg, value, valuelen);
  unlock_reader (app->slot);
  return err;
}
Example #10
0
void *gpuvm_xlate(void *hostptr, unsigned idev) {
	//fprintf(stderr, "xlating\n");
	// check arguments
	if(!hostptr || idev >= ndevs_g)
		return 0;
	
	// lock for reading
	if(lock_reader())
		return 0;

	// find host array and device buffer
	void *dev_buffer = 0;
	host_array_t *host_array = host_array_find_by_ptr(hostptr);
	if(host_array && host_array->links[idev])
		dev_buffer = host_array->links[idev]->buf;
	
	// unlock and return
	if(unlock_reader())
		return 0;
	return dev_buffer;
}  // gpuvm_xlate
Example #11
0
File: app.c Project: Juul/gnupg
/* Perform a VERIFY operation without doing anything lese.  This may
   be used to initialze a the PIN cache for long lasting other
   operations.  Its use is highly application dependent. */
gpg_error_t
app_check_pin (app_t app, const char *keyidstr,
               gpg_error_t (*pincb)(void*, const char *, char **),
               void *pincb_arg)
{
  gpg_error_t err;

  if (!app || !keyidstr || !*keyidstr || !pincb)
    return gpg_error (GPG_ERR_INV_VALUE);
  if (!app->ref_count)
    return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
  if (!app->fnc.check_pin)
    return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
  err = lock_reader (app->slot, NULL /*FIXME*/);
  if (err)
    return err;
  err = app->fnc.check_pin (app, keyidstr, pincb, pincb_arg);
  unlock_reader (app->slot);
  if (opt.verbose)
    log_info ("operation check_pin result: %s\n", gpg_strerror (err));
  return err;
}
Example #12
0
File: app.c Project: Juul/gnupg
/* Perform a GETATTR operation.  */
gpg_error_t
app_getattr (app_t app, ctrl_t ctrl, const char *name)
{
  gpg_error_t err;

  if (!app || !name || !*name)
    return gpg_error (GPG_ERR_INV_VALUE);
  if (!app->ref_count)
    return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);

  if (app->apptype && name && !strcmp (name, "APPTYPE"))
    {
      send_status_info (ctrl, "APPTYPE",
                        app->apptype, strlen (app->apptype), NULL, 0);
      return 0;
    }
  if (name && !strcmp (name, "SERIALNO"))
    {
      char *serial;
      time_t stamp;
      int rc;

      rc = app_get_serial_and_stamp (app, &serial, &stamp);
      if (rc)
        return rc;
      send_status_info (ctrl, "SERIALNO", serial, strlen (serial), NULL, 0);
      xfree (serial);
      return 0;
    }

  if (!app->fnc.getattr)
    return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
  err = lock_reader (app->slot, ctrl);
  if (err)
    return err;
  err =  app->fnc.getattr (app, ctrl, name);
  unlock_reader (app->slot);
  return err;
}
Example #13
0
File: app.c Project: Juul/gnupg
/* Perform a CHANGE REFERENCE DATA or RESET RETRY COUNTER operation.  */
gpg_error_t
app_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, int reset_mode,
                gpg_error_t (*pincb)(void*, const char *, char **),
                void *pincb_arg)
{
  gpg_error_t err;

  if (!app || !chvnostr || !*chvnostr || !pincb)
    return gpg_error (GPG_ERR_INV_VALUE);
  if (!app->ref_count)
    return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
  if (!app->fnc.change_pin)
    return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
  err = lock_reader (app->slot, ctrl);
  if (err)
    return err;
  err = app->fnc.change_pin (app, ctrl, chvnostr, reset_mode,
                             pincb, pincb_arg);
  unlock_reader (app->slot);
  if (opt.verbose)
    log_info ("operation change_pin result: %s\n", gpg_strerror (err));
  return err;
}
Example #14
0
File: app.c Project: Juul/gnupg
/* Read the key with ID KEYID.  On success a canonical encoded
   S-expression with the public key will get stored at PK and its
   length (for assertions) at PKLEN; the caller must release that
   buffer. On error NULL will be stored at PK and PKLEN and an error
   code returned.

   This function might not be supported by all applications.  */
gpg_error_t
app_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen)
{
  gpg_error_t err;

  if (pk)
    *pk = NULL;
  if (pklen)
    *pklen = 0;

  if (!app || !keyid || !pk || !pklen)
    return gpg_error (GPG_ERR_INV_VALUE);
  if (!app->ref_count)
    return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
  if (!app->fnc.readkey)
    return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
  err = lock_reader (app->slot, NULL /*FIXME*/);
  if (err)
    return err;
  err= app->fnc.readkey (app, keyid, pk, pklen);
  unlock_reader (app->slot);
  return err;
}
Example #15
0
File: app.c Project: Juul/gnupg
/* Write out the application specifig status lines for the LEARN
   command. */
gpg_error_t
app_write_learn_status (app_t app, ctrl_t ctrl, unsigned int flags)
{
  gpg_error_t err;

  if (!app)
    return gpg_error (GPG_ERR_INV_VALUE);
  if (!app->ref_count)
    return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
  if (!app->fnc.learn_status)
    return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);

  /* We do not send APPTYPE if only keypairinfo is requested.  */
  if (app->apptype && !(flags & 1))
    send_status_info (ctrl, "APPTYPE",
                      app->apptype, strlen (app->apptype), NULL, 0);
  err = lock_reader (app->slot, ctrl);
  if (err)
    return err;
  err = app->fnc.learn_status (app, ctrl, flags);
  unlock_reader (app->slot);
  return err;
}
Example #16
0
File: app.c Project: Juul/gnupg
/* If called with NAME as NULL, select the best fitting application
   and return a context; otherwise select the application with NAME
   and return a context.  SLOT identifies the reader device. Returns
   an error code and stores NULL at R_APP if no application was found
   or no card is present. */
gpg_error_t
select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app)
{
  gpg_error_t err;
  app_t app = NULL;
  unsigned char *result = NULL;
  size_t resultlen;
  int want_undefined;

  (void)ctrl;

  *r_app = NULL;

  want_undefined = (name && !strcmp (name, "undefined"));

  err = lock_reader (slot, ctrl);
  if (err)
    return err;

  /* First check whether we already have an application to share. */
  app = lock_table[slot].initialized ? lock_table[slot].app : NULL;
  if (app && name)
    if (!app->apptype || ascii_strcasecmp (app->apptype, name))
      {
        unlock_reader (slot);
        if (app->apptype)
          log_info ("application '%s' in use by reader %d - can't switch\n",
                    app->apptype, slot);
        return gpg_error (GPG_ERR_CONFLICT);
      }

  /* Don't use a non-reusable marked application.  */
  if (app && app->no_reuse)
    {
      unlock_reader (slot);
      log_info ("lingering application '%s' in use by reader %d"
                " - can't switch\n",
                app->apptype? app->apptype:"?", slot);
      return gpg_error (GPG_ERR_CONFLICT);
    }

  /* If we don't have an app, check whether we have a saved
     application for that slot.  This is useful so that a card does
     not get reset even if only one session is using the card - this
     way the PIN cache and other cached data are preserved.  */
  if (!app && lock_table[slot].initialized && lock_table[slot].last_app)
    {
      app = lock_table[slot].last_app;
      if (!name || (app->apptype && !ascii_strcasecmp (app->apptype, name)) )
        {
          /* Yes, we can reuse this application - either the caller
             requested an unspecific one or the requested one matches
             the saved one. */
          lock_table[slot].app = app;
          lock_table[slot].last_app = NULL;
        }
      else
        {
          /* No, this saved application can't be used - deallocate it. */
          lock_table[slot].last_app = NULL;
          deallocate_app (app);
          app = NULL;
        }
    }

  /* If we can reuse an application, bump the reference count and
     return it.  */
  if (app)
    {
      if (app->slot != slot)
        log_bug ("slot mismatch %d/%d\n", app->slot, slot);
      app->slot = slot;

      app->ref_count++;
      *r_app = app;
      unlock_reader (slot);
      return 0; /* Okay: We share that one. */
    }

  /* Need to allocate a new one.  */
  app = xtrycalloc (1, sizeof *app);
  if (!app)
    {
      err = gpg_error_from_syserror ();
      log_info ("error allocating context: %s\n", gpg_strerror (err));
      unlock_reader (slot);
      return err;
    }
  app->slot = slot;


  /* Fixme: We should now first check whether a card is at all
     present. */

  /* Try to read the GDO file first to get a default serial number.
     We skip this if the undefined application has been requested. */
  if (!want_undefined)
    {
      err = iso7816_select_file (slot, 0x3F00, 1, NULL, NULL);
      if (!err)
        err = iso7816_select_file (slot, 0x2F02, 0, NULL, NULL);
      if (!err)
        err = iso7816_read_binary (slot, 0, 0, &result, &resultlen);
      if (!err)
        {
          size_t n;
          const unsigned char *p;

          p = find_tlv_unchecked (result, resultlen, 0x5A, &n);
          if (p)
            resultlen -= (p-result);
          if (p && n > resultlen && n == 0x0d && resultlen+1 == n)
            {
              /* The object it does not fit into the buffer.  This is an
                 invalid encoding (or the buffer is too short.  However, I
                 have some test cards with such an invalid encoding and
                 therefore I use this ugly workaround to return something
                 I can further experiment with. */
              log_info ("enabling BMI testcard workaround\n");
              n--;
            }

          if (p && n <= resultlen)
            {
              /* The GDO file is pretty short, thus we simply reuse it for
                 storing the serial number. */
              memmove (result, p, n);
              app->serialno = result;
              app->serialnolen = n;
              err = app_munge_serialno (app);
              if (err)
                goto leave;
            }
          else
            xfree (result);
          result = NULL;
        }
    }

  /* For certain error codes, there is no need to try more.  */
  if (gpg_err_code (err) == GPG_ERR_CARD_NOT_PRESENT
      || gpg_err_code (err) == GPG_ERR_ENODEV)
    goto leave;

  /* Figure out the application to use.  */
  if (want_undefined)
    {
      /* We switch to the "undefined" application only if explicitly
         requested.  */
      app->apptype = "UNDEFINED";
      err = 0;
    }
  else
    err = gpg_error (GPG_ERR_NOT_FOUND);

  if (err && is_app_allowed ("openpgp")
          && (!name || !strcmp (name, "openpgp")))
    err = app_select_openpgp (app);
  if (err && is_app_allowed ("nks") && (!name || !strcmp (name, "nks")))
    err = app_select_nks (app);
  if (err && is_app_allowed ("p15") && (!name || !strcmp (name, "p15")))
    err = app_select_p15 (app);
  if (err && is_app_allowed ("geldkarte")
      && (!name || !strcmp (name, "geldkarte")))
    err = app_select_geldkarte (app);
  if (err && is_app_allowed ("dinsig") && (!name || !strcmp (name, "dinsig")))
    err = app_select_dinsig (app);
  if (err && name)
    err = gpg_error (GPG_ERR_NOT_SUPPORTED);

 leave:
  if (err)
    {
      if (name)
        log_info ("can't select application '%s': %s\n",
                  name, gpg_strerror (err));
      else
        log_info ("no supported card application found: %s\n",
                  gpg_strerror (err));
      xfree (app);
      unlock_reader (slot);
      return err;
    }

  app->ref_count = 1;

  lock_table[slot].app = app;
  *r_app = app;
  unlock_reader (slot);
  return 0;
}