scd: Remove unused files.
authorNIIBE Yutaka <gniibe@fsij.org>
Thu, 9 Jul 2015 03:44:11 +0000 (12:44 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Thu, 9 Jul 2015 03:51:03 +0000 (12:51 +0900)
* scd/Makefile.am (sc_copykeys_*): Remove.
* scd/sc-copykeys.c: Remove.
* scd/pcsc-wrapper.c: Remove.
* scd/{card-common.h,card-dinsig.c,card-p15.c,card.c}: Remove.

--

sc-copykeys doesn't work any more because it's based on old API.
pcsc-wrapper has gone because of nPth which is compatible to pthreads.
The card* files are old files, now we have app*.

scd/Makefile.am
scd/card-common.h [deleted file]
scd/card-dinsig.c [deleted file]
scd/card-p15.c [deleted file]
scd/card.c [deleted file]
scd/pcsc-wrapper.c [deleted file]
scd/sc-copykeys.c [deleted file]

index 6212e61..80e4c0f 100644 (file)
@@ -49,22 +49,3 @@ scdaemon_LDADD = $(libcommonpth) \
        $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(LIBASSUAN_LIBS) $(NPTH_LIBS) \
        $(LIBUSB_LIBS) $(GPG_ERROR_LIBS) \
         $(LIBINTL) $(DL_LIBS) $(NETLIBS) $(LIBICONV) $(resource_objs)
        $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(LIBASSUAN_LIBS) $(NPTH_LIBS) \
        $(LIBUSB_LIBS) $(GPG_ERROR_LIBS) \
         $(LIBINTL) $(DL_LIBS) $(NETLIBS) $(LIBICONV) $(resource_objs)
-
-# Removed for now: We need to decide whether it makes sense to
-# continue it at all, given that gpg has now all required
-# functionality.
-#sc_copykeys_SOURCES = \
-#      sc-copykeys.c scdaemon.h \
-#      apdu.c apdu.h \
-#      ccid-driver.c ccid-driver.h \
-#      iso7816.c iso7816.h \
-#      atr.c atr.h \
-#      app.c app-common.h app-help.c $(card_apps)
-#
-#sc_copykeys_LDADD = \
-#      ../common/libcommon.a \
-#      ../common/libsimple-pwquery.a \
-#      $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(LIBASSUAN_LIBS) $(NPTH_LIBS) \
-#       $(LIBUSB_LIBS) \
-#        -lgpg-error @LIBINTL@ @DL_LIBS@
-#
diff --git a/scd/card-common.h b/scd/card-common.h
deleted file mode 100644 (file)
index 640cec7..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/* card-common.h - Common declarations for all card types
- *     Copyright (C) 2001, 2002 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef CARD_COMMON_H
-#define CARD_COMMON_H
-
-/* Declaration of private data structure used by card-p15.c */
-struct p15private_s;
-
-
-struct card_ctx_s {
-  int reader;   /* used reader */
-  struct sc_context *ctx;
-  struct sc_card *scard;
-  struct sc_pkcs15_card *p15card; /* only if there is a pkcs15 application */
-  struct p15private_s *p15priv;   /* private data used by card-p15.c */
-
-  struct {
-    int initialized;  /* the card has been initialied and the function
-                         pointers may be used.  However for
-                         unsupported operations the particular
-                         function pointer is set to NULL */
-
-    int (*enum_keypairs) (CARD card, int idx,
-                          unsigned char *keygrip, char **keyid);
-    int (*enum_certs) (CARD card, int idx, char **certid, int *certtype);
-    int (*read_cert) (CARD card, const char *certidstr,
-                      unsigned char **cert, size_t *ncert);
-    int (*sign) (CARD card,
-                 const char *keyidstr, int hashalgo,
-                 int (pincb)(void*, const char *, char **),
-                 void *pincb_arg,
-                 const void *indata, size_t indatalen,
-                 unsigned char **outdata, size_t *outdatalen );
-    int (*decipher) (CARD card, const char *keyidstr,
-                     int (pincb)(void*, const char *, char **),
-                     void *pincb_arg,
-                     const void *indata, size_t indatalen,
-                     unsigned char **outdata, size_t *outdatalen);
-  } fnc;
-
-};
-
-/*-- card.c --*/
-gpg_error_t map_sc_err (int rc);
-int card_help_get_keygrip (ksba_cert_t cert, unsigned char *array);
-
-/*-- card-15.c --*/
-void p15_release_private_data (CARD card);
-
-/* constructors */
-void card_p15_bind (CARD card);
-void card_dinsig_bind (CARD card);
-
-
-#endif /*CARD_COMMON_H*/
diff --git a/scd/card-dinsig.c b/scd/card-dinsig.c
deleted file mode 100644 (file)
index 5be0061..0000000
+++ /dev/null
@@ -1,257 +0,0 @@
-/* card-dinsig.c - German signature law (DINSIG) functions
- *     Copyright (C) 2002 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/* The German signature law and its bylaw (SigG and SigV) is currently
-   used with an interface specification described in DIN V 66291-1.
-   The AID to be used is: 'D27600006601'.
-
-   The file IDs for certificates utilize the generic format:
-        Cxyz
-    C being the hex digit 'C' (12).
-    x being the service indicator:
-         '0' := SigG conform digital signature.
-         '1' := entity authentication.
-         '2' := key encipherment.
-         '3' := data encipherment.
-         '4' := key agreement.
-         other values are reserved for future use.
-    y being the security environment number using '0' for cards
-      not supporting a SE number.
-    z being the certificate type:
-         '0'        := C.CH (base certificate of ard holder) or C.ICC.
-         '1' .. '7' := C.CH (business or professional certificate
-                       of card holder.
-         '8' .. 'D' := C.CA (certificate of a CA issue by the Root-CA).
-         'E'        := C.RCA (self certified certificate of the Root-CA).
-         'F'        := reserved.
-
-   The file IDs used by default are:
-   '1F00'  EF.SSD (security service descriptor). [o,o]
-   '2F02'  EF.GDO (global data objects) [m,m]
-   'A000'  EF.PROT (signature log).  Cyclic file with 20 records of 53 byte.
-           Read and update after user authentication. [o,o]
-   'B000'  EF.PK.RCA.DS (public keys of Root-CA).  Size is 512b or size
-           of keys. [m (unless a 'C00E' is present),m]
-   'B001'  EF.PK.CA.DS (public keys of CAs).  Size is 512b or size
-           of keys. [o,o]
-   'C00n'  EF.C.CH.DS (digital signature certificate of card holder)
-           with n := 0 .. 7.  Size is 2k or size of cert.  Read and
-           update allowed after user authentication. [m,m]
-   'C00m'  EF.C.CA.DS (digital signature certificate of CA)
-           with m := 8 .. E.  Size is 1k or size of cert.  Read always
-           allowed, update after uder authentication. [o,o]
-   'C100'  EF.C.ICC.AUT (AUT certificate of ICC) [o,m]
-   'C108'  EF.C.CA.AUT (AUT certificate of CA) [o,m]
-   'D000'  EF.DM (display message) [-,m]
-
-   The letters in brackets indicate optional or mandatory files: The
-   first for card terminals under full control and the second for
-   "business" card terminals.
-
-   FIXME: Needs a lot more explanation.
-
-*/
-
-
-#include <config.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#ifdef HAVE_OPENSC
-#include <opensc/pkcs15.h>
-#include "scdaemon.h"
-#include <ksba.h>
-
-#include "card-common.h"
-
-static int dinsig_read_cert (CARD card, const char *certidstr,
-                             unsigned char **cert, size_t *ncert);
-
-
-
-/* See card.c for interface description.  Frankly we don't do any real
-   enumeration but just check whether the well know files are
-   available.  */
-static int
-dinsig_enum_keypairs (CARD card, int idx,
-                      unsigned char *keygrip, char **keyid)
-{
-  int rc;
-  unsigned char *buf;
-  size_t buflen;
-  ksba_cert_t cert;
-
-  /* fixme: We should locate the application via the EF(DIR) and not
-     assume a Netkey card */
-  if (!idx)
-    rc = dinsig_read_cert (card, "DINSIG-DF01.C000", &buf, &buflen);
-  else if (idx == 1)
-    rc = dinsig_read_cert (card, "DINSIG-DF01.C200", &buf, &buflen);
-  else
-    rc = -1;
-  if (rc)
-    return rc;
-
-  rc = ksba_cert_new (&cert);
-  if (rc)
-    {
-      xfree (buf);
-      return rc;
-    }
-
-  rc = ksba_cert_init_from_mem (cert, buf, buflen);
-  xfree (buf);
-  if (rc)
-    {
-      log_error ("failed to parse the certificate at idx %d: %s\n",
-                 idx, gpg_strerror (rc));
-      ksba_cert_release (cert);
-      return rc;
-    }
-  if (card_help_get_keygrip (cert, keygrip))
-    {
-      log_error ("failed to calculate the keygrip at index %d\n", idx);
-      ksba_cert_release (cert);
-      return gpg_error (GPG_ERR_CARD);
-    }
-  ksba_cert_release (cert);
-
-  /* return the iD */
-  if (keyid)
-    {
-      *keyid = xtrymalloc (17);
-      if (!*keyid)
-        return gpg_error (gpg_err_code_from_errno (errno));
-      if (!idx)
-        strcpy (*keyid, "DINSIG-DF01.C000");
-      else
-        strcpy (*keyid, "DINSIG-DF01.C200");
-    }
-
-  return 0;
-}
-
-
-\f
-/* See card.c for interface description */
-static int
-dinsig_read_cert (CARD card, const char *certidstr,
-                  unsigned char **cert, size_t *ncert)
-{
-  int rc;
-  struct sc_path path;
-  struct sc_file *file;
-  unsigned char *buf;
-  int buflen;
-
-  if (!strcmp (certidstr, "DINSIG-DF01.C000"))
-    sc_format_path ("3F00DF01C000", &path);
-  else if (!strcmp (certidstr, "DINSIG-DF01.C200"))
-    sc_format_path ("3F00DF01C200", &path);
-  else
-    return gpg_error (GPG_ERR_INV_ID);
-
-  rc = sc_select_file (card->scard, &path, &file);
-  if (rc)
-    {
-      log_error ("sc_select_file failed: %s\n", sc_strerror (rc));
-      return map_sc_err (rc);
-    }
-  if (file->type != SC_FILE_TYPE_WORKING_EF
-      || file->ef_structure != SC_FILE_EF_TRANSPARENT)
-    {
-      log_error ("wrong type or structure of certificate EF\n");
-      sc_file_free (file);
-      return gpg_error (GPG_ERR_CARD);
-    }
-  if (file->size < 20) /* check against a somewhat arbitrary length */
-    {
-      log_error ("certificate EF too short\n");
-      sc_file_free (file);
-      return gpg_error (GPG_ERR_CARD);
-    }
-  buf = xtrymalloc (file->size);
-  if (!buf)
-    {
-      gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
-      sc_file_free (file);
-      return tmperr;
-    }
-
-  rc = sc_read_binary (card->scard, 0, buf, file->size, 0);
-  if (rc >= 0 && rc != file->size)
-    {
-      log_error ("short read on certificate EF\n");
-      sc_file_free (file);
-      xfree (buf);
-      return gpg_error (GPG_ERR_CARD);
-    }
-  sc_file_free (file);
-  if (rc < 0)
-    {
-      log_error ("error reading certificate EF: %s\n", sc_strerror (rc));
-      xfree (buf);
-      return map_sc_err (rc);
-    }
-  buflen = rc;
-
-  /* The object is not a plain certificate but wrapped into id-at
-     userCertificate - fixme: we should check the specs and decided
-     whether libksba should support it */
-  if (buflen > 9 && buf[0] == 0x30 && buf[4] == 6 && buf[5] == 3
-      && buf[6] == 0x55 && buf[7] == 4 && buf[8] == 0x24)
-    {
-      /* We have to strip the padding.  Although this is a good idea
-         anyway, we have to do it due to a KSBA problem; KSBA does not
-         work correct when the buffer is larger than the ASN.1
-         structure and the certificates here are padded with FF.  So
-         as a workaround we look at the outer structure to get the
-         size of the entire thing and adjust the buflen.  We can only
-         do this when there is a 2 byte length field */
-      size_t seqlen;
-      if (buf[1] == 0x82)
-        {
-          seqlen = ((buf[2] << 8) | buf[3]) + 4;
-          if (seqlen < buflen)
-            buflen = seqlen;
-        }
-      memmove (buf, buf+9, buflen-9);
-      buflen -= 9;
-    }
-
-  *cert = buf;
-  *ncert = buflen;
-  return 0;
-}
-
-
-
-
-/* Bind our operations to the card */
-void
-card_dinsig_bind (CARD card)
-{
-  card->fnc.enum_keypairs = dinsig_enum_keypairs;
-  card->fnc.read_cert     = dinsig_read_cert;
-
-}
-#endif /*HAVE_OPENSC*/
diff --git a/scd/card-p15.c b/scd/card-p15.c
deleted file mode 100644 (file)
index 4af4472..0000000
+++ /dev/null
@@ -1,494 +0,0 @@
-/* card-p15.c - PKCS-15 based card access
- *     Copyright (C) 2002 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#ifdef HAVE_OPENSC
-#include <opensc/pkcs15.h>
-
-#include "scdaemon.h"
-#include <ksba.h>
-#include "card-common.h"
-
-
-struct p15private_s {
-  int n_prkey_rsa_objs;
-  struct sc_pkcs15_object *prkey_rsa_objs[32];
-  int n_cert_objs;
-  struct sc_pkcs15_object *cert_objs[32];
-};
-
-
-/* Allocate private data. */
-static int
-init_private_data (CARD card)
-{
-  struct p15private_s *priv;
-  int rc;
-
-  if (card->p15priv)
-    return 0; /* already done. */
-
-  priv = xtrycalloc (1, sizeof *priv);
-  if (!priv)
-    return gpg_error (gpg_err_code_from_errno (errno));
-
-  /* OpenSC (0.7.0) is a bit strange in that the get_objects functions
-     tries to be a bit too clever and implicitly does an enumeration
-     which eventually leads to the fact that every call to this
-     fucntion returns one more macthing object.  The old code in
-     p15_enum_keypairs assume that it would alwyas return the same
-     numer of objects and used this to figure out what the last object
-     enumerated is.  We now do an enum_objects just once and keep it
-     in the private data. */
-  rc = sc_pkcs15_get_objects (card->p15card, SC_PKCS15_TYPE_PRKEY_RSA,
-                              priv->prkey_rsa_objs,
-                              DIM (priv->prkey_rsa_objs));
-  if (rc < 0)
-    {
-      log_error ("private keys enumeration failed: %s\n", sc_strerror (rc));
-      xfree (priv);
-      return gpg_error (GPG_ERR_CARD);
-    }
-  priv->n_prkey_rsa_objs = rc;
-
-  /* Read all certificate objects. */
-  rc = sc_pkcs15_get_objects (card->p15card, SC_PKCS15_TYPE_CERT_X509,
-                              priv->cert_objs,
-                              DIM (priv->cert_objs));
-  if (rc < 0)
-    {
-      log_error ("private keys enumeration failed: %s\n", sc_strerror (rc));
-      xfree (priv);
-      return gpg_error (GPG_ERR_CARD);
-    }
-  priv->n_cert_objs = rc;
-
-  card->p15priv = priv;
-  return 0;
-}
-
-
-/* Release private data used in this module. */
-void
-p15_release_private_data (CARD card)
-{
-  if (!card->p15priv)
-    return;
-  xfree (card->p15priv);
-  card->p15priv = NULL;
-}
-
-
-
-/* See card.c for interface description */
-static int
-p15_enum_keypairs (CARD card, int idx,
-                   unsigned char *keygrip, char **keyid)
-{
-  int rc;
-  struct p15private_s *priv;
-  struct sc_pkcs15_object *tmpobj;
-  int nobjs;
-  struct sc_pkcs15_prkey_info *pinfo;
-  struct sc_pkcs15_cert_info *certinfo;
-  struct sc_pkcs15_cert      *certder;
-  ksba_cert_t cert;
-
-  rc = init_private_data (card);
-  if (rc)
-      return rc;
-  priv = card->p15priv;
-  nobjs = priv->n_prkey_rsa_objs;
-  rc = 0;
-  if (idx >= nobjs)
-    return -1;
-  pinfo = priv->prkey_rsa_objs[idx]->data;
-
-  /* now we need to read the certificate so that we can calculate the
-     keygrip */
-  rc = sc_pkcs15_find_cert_by_id (card->p15card, &pinfo->id, &tmpobj);
-  if (rc)
-    {
-      log_info ("certificate for private key %d not found: %s\n",
-                idx, sc_strerror (rc));
-      /* note, that we return the ID anyway */
-      rc = gpg_error (GPG_ERR_MISSING_CERT);
-      goto return_keyid;
-    }
-  certinfo = tmpobj->data;
-  rc = sc_pkcs15_read_certificate (card->p15card, certinfo, &certder);
-  if (rc)
-    {
-      log_info ("failed to read certificate for private key %d: %s\n",
-                idx, sc_strerror (rc));
-      return gpg_error (GPG_ERR_CARD);
-    }
-
-  rc = ksba_cert_new (&cert);
-  if (rc)
-    {
-      sc_pkcs15_free_certificate (certder);
-      return rc;
-    }
-  rc = ksba_cert_init_from_mem (cert, certder->data, certder->data_len);
-  sc_pkcs15_free_certificate (certder);
-  if (rc)
-    {
-      log_error ("failed to parse the certificate for private key %d: %s\n",
-                 idx, gpg_strerror (rc));
-      ksba_cert_release (cert);
-      return rc;
-    }
-  if (card_help_get_keygrip (cert, keygrip))
-    {
-      log_error ("failed to calculate the keygrip of private key %d\n", idx);
-      ksba_cert_release (cert);
-      return gpg_error (GPG_ERR_CARD);
-    }
-  ksba_cert_release (cert);
-
-  rc = 0;
- return_keyid:
-  if (keyid)
-    {
-      char *p;
-
-      *keyid = p = xtrymalloc (9+pinfo->id.len*2+1);
-      if (!*keyid)
-        return gpg_error (gpg_err_code_from_errno (errno));
-      p = stpcpy (p, "P15-5015.");
-      bin2hex (pinfo->id.value, pinfo->id.len, p);
-    }
-
-  return rc;
-}
-
-/* See card.c for interface description */
-static int
-p15_enum_certs (CARD card, int idx, char **certid, int *type)
-{
-  int rc;
-  struct p15private_s *priv;
-  struct sc_pkcs15_object *obj;
-  struct sc_pkcs15_cert_info *cinfo;
-  int nobjs;
-
-  rc = init_private_data (card);
-  if (rc)
-      return rc;
-  priv = card->p15priv;
-  nobjs = priv->n_cert_objs;
-  rc = 0;
-  if (idx >= nobjs)
-    return -1;
-  obj =  priv->cert_objs[idx];
-  cinfo = obj->data;
-
-  if (certid)
-    {
-      char *p;
-      int i;
-
-      *certid = p = xtrymalloc (9+cinfo->id.len*2+1);
-      if (!*certid)
-        return gpg_error (gpg_err_code_from_errno (errno));
-      p = stpcpy (p, "P15-5015.");
-      bin2hex (cinfo->id.value, cinfo->id.len, p);
-    }
-  if (type)
-    {
-      if (!obj->df)
-        *type = 0; /* unknown */
-      else if (obj->df->type == SC_PKCS15_CDF)
-        *type = 100;
-      else if (obj->df->type == SC_PKCS15_CDF_TRUSTED)
-        *type = 101;
-      else if (obj->df->type == SC_PKCS15_CDF_USEFUL)
-        *type = 102;
-      else
-        *type = 0; /* error -> unknown */
-    }
-
-  return rc;
-}
-
-
-\f
-static int
-idstr_to_id (const char *idstr, struct sc_pkcs15_id *id)
-{
-  const char *s;
-  int n;
-
-  /* For now we only support the standard DF */
-  if (strncmp (idstr, "P15-5015.", 9) )
-    return gpg_error (GPG_ERR_INV_ID);
-  for (s=idstr+9, n=0; hexdigitp (s); s++, n++)
-    ;
-  if (*s || (n&1))
-    return gpg_error (GPG_ERR_INV_ID); /*invalid or odd number of digits*/
-  n /= 2;
-  if (!n || n > SC_PKCS15_MAX_ID_SIZE)
-    return gpg_error (GPG_ERR_INV_ID); /* empty or too large */
-  for (s=idstr+9, n=0; *s; s += 2, n++)
-    id->value[n] = xtoi_2 (s);
-  id->len = n;
-  return 0;
-}
-
-
-/* See card.c for interface description */
-static int
-p15_read_cert (CARD card, const char *certidstr,
-               unsigned char **cert, size_t *ncert)
-{
-  struct sc_pkcs15_object *tmpobj;
-  struct sc_pkcs15_id certid;
-  struct sc_pkcs15_cert_info *certinfo;
-  struct sc_pkcs15_cert      *certder;
-  int rc;
-
-  if (!card || !certidstr || !cert || !ncert)
-    return gpg_error (GPG_ERR_INV_VALUE);
-  if (!card->p15card)
-    return gpg_error (GPG_ERR_NO_PKCS15_APP);
-
-  rc = idstr_to_id (certidstr, &certid);
-  if (rc)
-    return rc;
-
-  rc = sc_pkcs15_find_cert_by_id (card->p15card, &certid, &tmpobj);
-  if (rc)
-    {
-      log_info ("certificate '%s' not found: %s\n",
-                certidstr, sc_strerror (rc));
-      return -1;
-    }
-  certinfo = tmpobj->data;
-  rc = sc_pkcs15_read_certificate (card->p15card, certinfo, &certder);
-  if (rc)
-    {
-      log_info ("failed to read certificate '%s': %s\n",
-                certidstr, sc_strerror (rc));
-      return gpg_error (GPG_ERR_CARD);
-    }
-
-  *cert = xtrymalloc (certder->data_len);
-  if (!*cert)
-    {
-      gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
-      sc_pkcs15_free_certificate (certder);
-      return tmperr;
-    }
-  memcpy (*cert, certder->data, certder->data_len);
-  *ncert = certder->data_len;
-  sc_pkcs15_free_certificate (certder);
-  return 0;
-}
-
-
-
-
-\f
-static int
-p15_prepare_key (CARD card, const char *keyidstr,
-                 int (pincb)(void*, const char *, char **),
-                 void *pincb_arg, struct sc_pkcs15_object **r_keyobj)
-{
-  struct sc_pkcs15_id keyid;
-  struct sc_pkcs15_pin_info *pin;
-  struct sc_pkcs15_object *keyobj, *pinobj;
-  char *pinvalue;
-  int rc;
-
-  rc = idstr_to_id (keyidstr, &keyid);
-  if (rc)
-    return rc;
-
-  rc = sc_pkcs15_find_prkey_by_id (card->p15card, &keyid, &keyobj);
-  if (rc < 0)
-    {
-      log_error ("private key not found: %s\n", sc_strerror(rc));
-      return gpg_error (GPG_ERR_NO_SECKEY);
-    }
-
-  rc = sc_pkcs15_find_pin_by_auth_id (card->p15card,
-                                      &keyobj->auth_id, &pinobj);
-  if (rc)
-    {
-      log_error ("failed to find PIN by auth ID: %s\n", sc_strerror (rc));
-      return gpg_error (GPG_ERR_BAD_PIN_METHOD);
-    }
-  pin = pinobj->data;
-
-  /* Fixme: pack this into a verification loop */
-  /* Fixme: we might want to pass pin->min_length and
-     pin->stored_length */
-  rc = pincb (pincb_arg, pinobj->label, &pinvalue);
-  if (rc)
-    {
-      log_info ("PIN callback returned error: %s\n", gpg_strerror (rc));
-      return rc;
-    }
-
-  rc = sc_pkcs15_verify_pin (card->p15card, pin,
-                             pinvalue, strlen (pinvalue));
-  xfree (pinvalue);
-  if (rc)
-    {
-      log_info ("PIN verification failed: %s\n", sc_strerror (rc));
-      return gpg_error (GPG_ERR_BAD_PIN);
-    }
-
-  /* fixme: check wheter we need to release KEYOBJ in case of an error */
-  *r_keyobj = keyobj;
-  return 0;
-}
-
-
-/* See card.c for interface description */
-static int
-p15_sign (CARD card, const char *keyidstr, int hashalgo,
-          int (pincb)(void*, const char *, char **),
-          void *pincb_arg,
-          const void *indata, size_t indatalen,
-          unsigned char **outdata, size_t *outdatalen )
-{
-  unsigned int cryptflags;
-  struct sc_pkcs15_object *keyobj;
-  int rc;
-  unsigned char *outbuf = NULL;
-  size_t outbuflen;
-
-  if (hashalgo != GCRY_MD_SHA1)
-    return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
-
-  rc = p15_prepare_key (card, keyidstr, pincb, pincb_arg, &keyobj);
-  if (rc)
-    return rc;
-
-  cryptflags = SC_ALGORITHM_RSA_PAD_PKCS1;
-
-  outbuflen = 1024;
-  outbuf = xtrymalloc (outbuflen);
-  if (!outbuf)
-    return gpg_error (gpg_err_code_from_errno (errno));
-
-  rc = sc_pkcs15_compute_signature (card->p15card, keyobj,
-                                    cryptflags,
-                                    indata, indatalen,
-                                    outbuf, outbuflen );
-  if (rc < 0)
-    {
-      log_error ("failed to create signature: %s\n", sc_strerror (rc));
-      rc = gpg_error (GPG_ERR_CARD);
-    }
-  else
-    {
-      *outdatalen = rc;
-      *outdata = outbuf;
-      outbuf = NULL;
-      rc = 0;
-    }
-
-  xfree (outbuf);
-  return rc;
-}
-
-
-/* See card.c for description */
-static int
-p15_decipher (CARD card, const char *keyidstr,
-              int (pincb)(void*, const char *, char **),
-              void *pincb_arg,
-              const void *indata, size_t indatalen,
-              unsigned char **outdata, size_t *outdatalen )
-{
-  struct sc_pkcs15_object *keyobj;
-  int rc;
-  unsigned char *outbuf = NULL;
-  size_t outbuflen;
-
-  rc = p15_prepare_key (card, keyidstr, pincb, pincb_arg, &keyobj);
-  if (rc)
-    return rc;
-
-  if (card && card->scard && card->scard->driver
-      && !strcasecmp (card->scard->driver->short_name, "tcos"))
-    {
-      /* very ugly hack to force the use of a local key.  We need this
-         until we have fixed the initialization code for TCOS cards */
-      struct sc_pkcs15_prkey_info *prkey = keyobj->data;
-      if ( !(prkey->key_reference & 0x80))
-        {
-          prkey->key_reference |= 0x80;
-          log_debug ("using TCOS hack to force the use of local keys\n");
-        }
-      if (*keyidstr && keyidstr[strlen(keyidstr)-1] == '6')
-        {
-          prkey->key_reference |= 1;
-          log_debug ("warning: using even more TCOS hacks\n");
-        }
-    }
-
-  outbuflen = indatalen < 256? 256 : indatalen;
-  outbuf = xtrymalloc (outbuflen);
-  if (!outbuf)
-    return gpg_error (gpg_err_code_from_errno (errno));
-
-  rc = sc_pkcs15_decipher (card->p15card, keyobj,
-                           0,
-                           indata, indatalen,
-                           outbuf, outbuflen);
-  if (rc < 0)
-    {
-      log_error ("failed to decipher the data: %s\n", sc_strerror (rc));
-      rc = gpg_error (GPG_ERR_CARD);
-    }
-  else
-    {
-      *outdatalen = rc;
-      *outdata = outbuf;
-      outbuf = NULL;
-      rc = 0;
-    }
-
-  xfree (outbuf);
-  return rc;
-}
-
-
-
-/* Bind our operations to the card */
-void
-card_p15_bind (CARD card)
-{
-  card->fnc.enum_keypairs = p15_enum_keypairs;
-  card->fnc.enum_certs    = p15_enum_certs;
-  card->fnc.read_cert     = p15_read_cert;
-  card->fnc.sign          = p15_sign;
-  card->fnc.decipher      = p15_decipher;
-}
-#endif /*HAVE_OPENSC*/
diff --git a/scd/card.c b/scd/card.c
deleted file mode 100644 (file)
index a582c50..0000000
+++ /dev/null
@@ -1,568 +0,0 @@
-/* card.c - SCdaemon card functions
- *     Copyright (C) 2002 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#ifdef HAVE_OPENSC
-#include <opensc/pkcs15.h>
-#endif
-
-#include "scdaemon.h"
-#include <ksba.h>
-
-#include "card-common.h"
-
-/* Map the SC error codes to the GNUPG ones */
-gpg_error_t
-map_sc_err (int rc)
-{
-  gpg_err_code_t e;
-
-  switch (rc)
-    {
-    case 0: e = 0; break;
-#ifdef HAVE_OPENSC
-    case SC_ERROR_NOT_SUPPORTED:         e = GPG_ERR_NOT_SUPPORTED; break;
-    case SC_ERROR_PKCS15_APP_NOT_FOUND:  e = GPG_ERR_NO_PKCS15_APP; break;
-    case SC_ERROR_OUT_OF_MEMORY:         e = GPG_ERR_ENOMEM; break;
-    case SC_ERROR_CARD_NOT_PRESENT:      e = GPG_ERR_CARD_NOT_PRESENT; break;
-    case SC_ERROR_CARD_REMOVED:          e = GPG_ERR_CARD_REMOVED; break;
-    case SC_ERROR_INVALID_CARD:          e = GPG_ERR_INV_CARD; break;
-#endif
-    default: e = GPG_ERR_CARD; break;
-    }
-  /* It does not make much sense to further distingusih the error
-     source between OpenSC and SCD.  Thus we use SCD as source
-     here. */
-  return gpg_err_make (GPG_ERR_SOURCE_SCD, e);
-}
-
-/* Get the keygrip from CERT, return 0 on success */
-int
-card_help_get_keygrip (ksba_cert_t cert, unsigned char *array)
-{
-  gcry_sexp_t s_pkey;
-  int rc;
-  ksba_sexp_t p;
-  size_t n;
-
-  p = ksba_cert_get_public_key (cert);
-  if (!p)
-    return -1; /* oops */
-  n = gcry_sexp_canon_len (p, 0, NULL, NULL);
-  if (!n)
-    return -1; /* libksba did not return a proper S-expression */
-  rc = gcry_sexp_sscan ( &s_pkey, NULL, p, n);
-  xfree (p);
-  if (rc)
-    return -1; /* can't parse that S-expression */
-  array = gcry_pk_get_keygrip (s_pkey, array);
-  gcry_sexp_release (s_pkey);
-  if (!array)
-    return -1; /* failed to calculate the keygrip */
-  return 0;
-}
-
-
-
-
-
-
-\f
-/* Create a new context for the card and figures out some basic
-   information of the card.  Detects whether a PKCS_15 application is
-   stored.
-
-   Common errors: GPG_ERR_CARD_NOT_PRESENT */
-int
-card_open (CARD *rcard)
-{
-#ifdef HAVE_OPENSC
-  CARD card;
-  int rc;
-
-  if (opt.disable_opensc)
-    return gpg_error (GPG_ERR_NOT_SUPPORTED);
-
-  card = xtrycalloc (1, sizeof *card);
-  if (!card)
-    return gpg_error (gpg_err_code_from_errno (errno));
-  card->reader = 0;
-
-  rc = sc_establish_context (&card->ctx, "scdaemon");
-  if (rc)
-    {
-      log_error ("failed to establish SC context: %s\n", sc_strerror (rc));
-      rc = map_sc_err (rc);
-      goto leave;
-    }
-  if (card->reader >= card->ctx->reader_count)
-    {
-      log_error ("no card reader available\n");
-      rc = gpg_error (GPG_ERR_CARD);
-      goto leave;
-    }
-  card->ctx->error_file = log_get_stream ();
-  card->ctx->debug = opt.debug_sc;
-  card->ctx->debug_file = log_get_stream ();
-
-  if (sc_detect_card_presence (card->ctx->reader[card->reader], 0) != 1)
-    {
-      rc = gpg_error (GPG_ERR_CARD_NOT_PRESENT);
-      goto leave;
-    }
-
-  rc = sc_connect_card (card->ctx->reader[card->reader], 0, &card->scard);
-  if (rc)
-    {
-      log_error ("failed to connect card in reader %d: %s\n",
-                 card->reader, sc_strerror (rc));
-      rc = map_sc_err (rc);
-      goto leave;
-    }
-  if (opt.verbose)
-    log_info ("connected to card in reader %d using driver '%s'\n",
-              card->reader, card->scard->driver->name);
-
-  rc = sc_lock (card->scard);
-  if (rc)
-    {
-      log_error ("can't lock card in reader %d: %s\n",
-                 card->reader, sc_strerror (rc));
-      rc = map_sc_err (rc);
-      goto leave;
-    }
-
-
- leave:
-  if (rc)
-    card_close (card);
-  else
-    *rcard = card;
-
-  return rc;
-#else
-  return gpg_error (GPG_ERR_NOT_SUPPORTED);
-#endif
-}
-
-
-/* Close a card and release all resources */
-void
-card_close (CARD card)
-{
-  if (card)
-    {
-#ifdef HAVE_OPENSC
-      if (card->p15card)
-        {
-          sc_pkcs15_unbind (card->p15card);
-          card->p15card = NULL;
-        }
-      if (card->p15priv)
-        p15_release_private_data (card);
-      if (card->scard)
-        {
-          sc_unlock (card->scard);
-          sc_disconnect_card (card->scard, 0);
-          card->scard = NULL;
-       }
-      if (card->ctx)
-        {
-          sc_release_context (card->ctx);
-          card->ctx = NULL;
-        }
-#endif
-      xfree (card);
-    }
-}
-
-/* Locate a simple TLV encoded data object in BUFFER of LENGTH and
-   return a pointer to value as well as its length in NBYTES.  Return
-   NULL if it was not found.  Note, that the function does not check
-   whether the value fits into the provided buffer. */
-#ifdef HAVE_OPENSC
-static const char *
-find_simple_tlv (const unsigned char *buffer, size_t length,
-                 int tag, size_t *nbytes)
-{
-  const char *s = buffer;
-  size_t n = length;
-  size_t len;
-
-  for (;;)
-    {
-      buffer = s;
-      if (n < 2)
-        return NULL; /* buffer too short for tag and length. */
-      len = s[1];
-      s += 2; n -= 2;
-      if (len == 255)
-        {
-          if (n < 2)
-            return NULL; /* we expected 2 more bytes with the length. */
-          len = (s[0] << 8) | s[1];
-          s += 2; n -= 2;
-        }
-      if (*buffer == tag)
-        {
-          *nbytes = len;
-          return s;
-        }
-      if (len > n)
-        return NULL; /* buffer too short to skip to the next tag. */
-      s += len; n -= len;
-    }
-}
-#endif /*HAVE_OPENSC*/
-
-/* Find the ICC Serial Number within the provided BUFFER of LENGTH
-   (which should contain the GDO file) and return it as a hex encoded
-   string and allocated string in SERIAL.  Return an error code when
-   the ICCSN was not found. */
-#ifdef HAVE_OPENSC
-static int
-find_iccsn (const unsigned char *buffer, size_t length, char **serial)
-{
-  size_t n;
-  const unsigned char *s;
-  char *p;
-
-  s = find_simple_tlv (buffer, length, 0x5A, &n);
-  if (!s)
-    return gpg_error (GPG_ERR_CARD);
-  length -= s - buffer;
-  if (n > length)
-    {
-      /* Oops, 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. */
-      if (n == 0x0D && length+1 == n)
-        {
-          log_debug ("enabling BMI testcard workaround\n");
-          n--;
-        }
-      else
-        return gpg_error (GPG_ERR_CARD); /* Bad encoding; does
-                                           not fit into buffer. */
-    }
-  if (!n)
-    return gpg_error (GPG_ERR_CARD); /* Well, that is too short. */
-
-  *serial = p = xtrymalloc (2*n+1);
-  if (!*serial)
-    return gpg_error (gpg_err_code_from_errno (errno));
-  for (; n; n--, p += 2, s++)
-    sprintf (p, "%02X", *s);
-  *p = 0;
-  return 0;
-}
-#endif /*HAVE_OPENSC*/
-
-/* Retrieve the serial number and the time of the last update of the
-   card.  The serial number is returned as a malloced string (hex
-   encoded) in SERIAL and the time of update is returned in STAMP.
-   If no update time is available the returned value is 0.  The serial
-   is mandatory for a PKCS_15 application and an error will be
-   returned if this value is not availbale.  For non-PKCS-15 cards a
-   serial number is constructed by other means. Caller must free
-   SERIAL unless the function returns an error. */
-int
-card_get_serial_and_stamp (CARD card, char **serial, time_t *stamp)
-{
-#ifdef HAVE_OPENSC
-  int rc;
-  struct sc_path path;
-  struct sc_file *file;
-  unsigned char buf[256];
-  int buflen;
-#endif
-
-  if (!card || !serial || !stamp)
-    return gpg_error (GPG_ERR_INV_VALUE);
-
-  *serial = NULL;
-  *stamp = 0; /* not available */
-
-#ifdef HAVE_OPENSC
-  if (!card->fnc.initialized)
-    {
-      card->fnc.initialized = 1;
-      /* The first use of this card tries to figure out the type of the card
-         and sets up the function pointers. */
-      rc = sc_pkcs15_bind (card->scard, &card->p15card);
-      if (rc)
-        {
-          if (rc != SC_ERROR_PKCS15_APP_NOT_FOUND)
-            log_error ("binding of existing PKCS-15 failed in reader %d: %s\n",
-                       card->reader, sc_strerror (rc));
-          card->p15card = NULL;
-          rc = 0;
-        }
-      if (card->p15card)
-        card_p15_bind (card);
-      card->fnc.initialized = 1;
-    }
-
-
-  /* We should lookup the iso 7812-1 and 8583-3 - argh ISO
-     practice is suppressing innovation - IETF rules!  So we
-     always get the serialnumber from the 2F02 GDO file.  */
-  /* FIXME: in case we can't parse the 2F02 EF and we have a P15 card,
-     we should get the serial number from the respective P15 file */
-  sc_format_path ("3F002F02", &path);
-  rc = sc_select_file (card->scard, &path, &file);
-  if (rc)
-    {
-      log_error ("sc_select_file failed: %s\n", sc_strerror (rc));
-      return gpg_error (GPG_ERR_CARD);
-    }
-  if (file->type != SC_FILE_TYPE_WORKING_EF
-      || file->ef_structure != SC_FILE_EF_TRANSPARENT)
-    {
-      log_error ("wrong type or structure of GDO file\n");
-      sc_file_free (file);
-      return gpg_error (GPG_ERR_CARD);
-    }
-
-  if (!file->size || file->size >= DIM(buf) )
-    { /* FIXME: Use a real parser */
-      log_error ("unsupported size of GDO file (%d)\n", file->size);
-      sc_file_free (file);
-      return gpg_error (GPG_ERR_CARD);
-    }
-  buflen = file->size;
-
-  rc = sc_read_binary (card->scard, 0, buf, buflen, 0);
-  sc_file_free (file);
-  if (rc < 0)
-    {
-      log_error ("error reading GDO file: %s\n", sc_strerror (rc));
-      return gpg_error (GPG_ERR_CARD);
-    }
-  if (rc != buflen)
-    {
-      log_error ("short read on GDO file\n");
-      return gpg_error (GPG_ERR_CARD);
-    }
-
-  rc = find_iccsn (buf, buflen, serial);
-  if (gpg_err_code (rc) == GPG_ERR_CARD)
-    log_error ("invalid structure of GDO file\n");
-  if (!rc && card->p15card && !strcmp (*serial, "D27600000000000000000000"))
-    { /* This is a German card with a silly serial number.  Try to get
-         the serial number from the EF(TokenInfo). We indicate such a
-         serial number by the using the prefix: "FF0100". */
-      const char *efser = card->p15card->serial_number;
-      char *p;
-
-      if (!efser)
-        efser = "";
-
-      xfree (*serial);
-      *serial = NULL;
-      p = xtrymalloc (strlen (efser) + 7);
-      if (!p)
-          rc = gpg_error (gpg_err_code_from_errno (errno));
-      else
-        {
-          strcpy (p, "FF0100");
-          strcpy (p+6, efser);
-          *serial = p;
-        }
-    }
-  else if (!rc && **serial == 'F' && (*serial)[1] == 'F')
-    { /* The serial number starts with our special prefix.  This
-         requires that we put our default prefix "FF0000" in front. */
-      char *p = xtrymalloc (strlen (*serial) + 7);
-      if (!p)
-        {
-          xfree (*serial);
-          *serial = NULL;
-          rc = gpg_error (gpg_err_code_from_errno (errno));
-        }
-      else
-        {
-          strcpy (p, "FF0000");
-          strcpy (p+6, *serial);
-          xfree (*serial);
-          *serial = p;
-        }
-    }
-  return rc;
-#else
-  return gpg_error (GPG_ERR_NOT_SUPPORTED);
-#endif
-}
-
-
-/* Enumerate all keypairs on the card and return the Keygrip as well
-   as the internal identification of the key.  KEYGRIP must be a
-   caller provided buffer with a size of 20 bytes which will receive
-   the KEYGRIP of the keypair.  If KEYID is not NULL, it returns the
-   ID field of the key in allocated memory; this is a string without
-   spaces.  The function returns -1 when all keys have been
-   enumerated.  Note that the error GPG_ERR_MISSING_CERTIFICATE may be
-   returned if there is just the private key but no public key (ie.e a
-   certificate) available.  Applications might want to continue
-   enumerating after this error.*/
-int
-card_enum_keypairs (CARD card, int idx,
-                    unsigned char *keygrip,
-                    char **keyid)
-{
-  int rc;
-
-  if (keyid)
-    *keyid = NULL;
-
-  if (!card || !keygrip)
-    return gpg_error (GPG_ERR_INV_VALUE);
-  if (idx < 0)
-    return gpg_error (GPG_ERR_INV_INDEX);
-  if (!card->fnc.initialized)
-    return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
-  if (!card->fnc.enum_keypairs)
-    return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
-  rc = card->fnc.enum_keypairs (card, idx, keygrip, keyid);
-  if (opt.verbose)
-    log_info ("card operation enum_keypairs result: %s\n",
-              gpg_strerror (rc));
-  return rc;
-}
-
-
-/* Enumerate all trusted certificates available on the card, return
-   their ID in CERT and the type in CERTTYPE.  Types of certificates
-   are:
-      0   := Unknown
-      100 := Regular X.509 cert
-      101 := Trusted X.509 cert
-      102 := Useful X.509 cert
-      110 := Root CA cert (DINSIG)
- */
-int
-card_enum_certs (CARD card, int idx, char **certid, int *certtype)
-{
-  int rc;
-
-  if (certid)
-    *certid = NULL;
-
-  if (!card)
-    return gpg_error (GPG_ERR_INV_VALUE);
-  if (idx < 0)
-    return gpg_error (GPG_ERR_INV_INDEX);
-  if (!card->fnc.initialized)
-    return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
-  if (!card->fnc.enum_certs)
-    return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
-  rc = card->fnc.enum_certs (card, idx, certid, certtype);
-  if (opt.verbose)
-    log_info ("card operation enum_certs result: %s\n",
-              gpg_strerror (rc));
-  return rc;
-}
-
-
-
-/* Read the certificate identified by CERTIDSTR which is the
-   hexadecimal encoded ID of the certificate, prefixed with the string
-   "3F005015.". The certificate is return in DER encoded form in CERT
-   and NCERT. */
-int
-card_read_cert (CARD card, const char *certidstr,
-                unsigned char **cert, size_t *ncert)
-{
-  int rc;
-
-  if (!card || !certidstr || !cert || !ncert)
-    return gpg_error (GPG_ERR_INV_VALUE);
-  if (!card->fnc.initialized)
-    return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
-  if (!card->fnc.read_cert)
-    return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
-  rc = card->fnc.read_cert (card, certidstr, cert, ncert);
-  if (opt.verbose)
-    log_info ("card operation read_cert result: %s\n", gpg_strerror (rc));
-  return rc;
-}
-
-
-/* Create the signature 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.  */
-int
-card_sign (CARD card, const char *keyidstr, int hashalgo,
-           int (pincb)(void*, const char *, char **),
-           void *pincb_arg,
-           const void *indata, size_t indatalen,
-           unsigned char **outdata, size_t *outdatalen )
-{
-  int rc;
-
-  if (!card || !indata || !indatalen || !outdata || !outdatalen || !pincb)
-    return gpg_error (GPG_ERR_INV_VALUE);
-  if (!card->fnc.initialized)
-    return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
-  if (!card->fnc.sign)
-    return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
-  rc =  card->fnc.sign (card, keyidstr, hashalgo,
-                        pincb, pincb_arg,
-                        indata, indatalen,
-                        outdata, outdatalen);
-  if (opt.verbose)
-    log_info ("card operation sign result: %s\n", gpg_strerror (rc));
-  return rc;
-}
-
-
-/* Create the signature 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.  */
-int
-card_decipher (CARD card, const char *keyidstr,
-               int (pincb)(void*, const char *, char **),
-               void *pincb_arg,
-               const void *indata, size_t indatalen,
-               unsigned char **outdata, size_t *outdatalen )
-{
-  int rc;
-
-  if (!card || !indata || !indatalen || !outdata || !outdatalen || !pincb)
-    return gpg_error (GPG_ERR_INV_VALUE);
-  if (!card->fnc.initialized)
-    return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
-  if (!card->fnc.decipher)
-    return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
-  rc =  card->fnc.decipher (card, keyidstr,
-                            pincb, pincb_arg,
-                            indata, indatalen,
-                            outdata, outdatalen);
-  if (opt.verbose)
-    log_info ("card operation decipher result: %s\n", gpg_strerror (rc));
-  return rc;
-}
diff --git a/scd/pcsc-wrapper.c b/scd/pcsc-wrapper.c
deleted file mode 100644 (file)
index 843603a..0000000
+++ /dev/null
@@ -1,911 +0,0 @@
-/* pcsc-wrapper.c - Wrapper for accessing the PC/SC service
- *     Copyright (C) 2003, 2004 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-  This wrapper is required to handle problems with the libpscslite
-  library.  That library assumes that pthreads are used and fails
-  badly if one tries to use it with a process using Pth.  Note that
-  the wrapper is not required if nPth is used.
-
-  The operation model is pretty simple: It reads requests from stdin
-  and returns the answer on stdout.  There is no direct mapping to the
-  pcsc interface but to a higher level one which resembles the code
-  used in scdaemon (apdu.c) when not using Pth or while running under
-  Windows.
-
-  The interface is binary consisting of a command tag and the length
-  of the parameter list.  The calling process needs to pass the
-  version number of the interface on the command line to make sure
-  that both agree on the same interface.  For each port a separate
-  instance of this process needs to be started.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <assert.h>
-#include <dlfcn.h>
-
-
-#define PGM "pcsc-wrapper"
-
-/* Allow for a standalone build. */
-#ifdef VERSION
-#define MYVERSION_LINE PGM " ("GNUPG_NAME") " VERSION
-#define BUGREPORT_LINE "\nReport bugs to <bug-gnupg@gnu.org>.\n"
-#else
-#define MYVERSION_LINE PGM
-#define BUGREPORT_LINE ""
-#endif
-
-#define DEFAULT_PCSC_DRIVER "libpcsclite.so"
-
-
-static int verbose;
-
-#if defined(__APPLE__) || defined(_WIN32) || defined(__CYGWIN__)
-typedef unsigned int pcsc_dword_t;
-#else
-typedef unsigned long pcsc_dword_t;
-#endif
-
-
-/* PC/SC constants and function pointer. */
-#define PCSC_SCOPE_USER      0
-#define PCSC_SCOPE_TERMINAL  1
-#define PCSC_SCOPE_SYSTEM    2
-#define PCSC_SCOPE_GLOBAL    3
-
-#define PCSC_PROTOCOL_T0     1
-#define PCSC_PROTOCOL_T1     2
-#define PCSC_PROTOCOL_RAW    4
-
-#define PCSC_SHARE_EXCLUSIVE 1
-#define PCSC_SHARE_SHARED    2
-#define PCSC_SHARE_DIRECT    3
-
-#define PCSC_LEAVE_CARD      0
-#define PCSC_RESET_CARD      1
-#define PCSC_UNPOWER_CARD    2
-#define PCSC_EJECT_CARD      3
-
-#define PCSC_UNKNOWN    0x0001
-#define PCSC_ABSENT     0x0002  /* Card is absent.  */
-#define PCSC_PRESENT    0x0004  /* Card is present.  */
-#define PCSC_SWALLOWED  0x0008  /* Card is present and electrical connected. */
-#define PCSC_POWERED    0x0010  /* Card is powered.  */
-#define PCSC_NEGOTIABLE 0x0020  /* Card is awaiting PTS.  */
-#define PCSC_SPECIFIC   0x0040  /* Card is ready for use.  */
-
-#define PCSC_STATE_UNAWARE     0x0000  /* Want status.  */
-#define PCSC_STATE_IGNORE      0x0001  /* Ignore this reader.  */
-#define PCSC_STATE_CHANGED     0x0002  /* State has changed.  */
-#define PCSC_STATE_UNKNOWN     0x0004  /* Reader unknown.  */
-#define PCSC_STATE_UNAVAILABLE 0x0008  /* Status unavailable.  */
-#define PCSC_STATE_EMPTY       0x0010  /* Card removed.  */
-#define PCSC_STATE_PRESENT     0x0020  /* Card inserted.  */
-#define PCSC_STATE_ATRMATCH    0x0040  /* ATR matches card. */
-#define PCSC_STATE_EXCLUSIVE   0x0080  /* Exclusive Mode.  */
-#define PCSC_STATE_INUSE       0x0100  /* Shared mode.  */
-#define PCSC_STATE_MUTE               0x0200  /* Unresponsive card.  */
-
-struct pcsc_io_request_s {
-  unsigned long protocol;
-  unsigned long pci_len;
-};
-
-typedef struct pcsc_io_request_s *pcsc_io_request_t;
-
-#ifdef __APPLE__
-#pragma pack(1)
-#endif
-
-struct pcsc_readerstate_s
-{
-  const char *reader;
-  void *user_data;
-  pcsc_dword_t current_state;
-  pcsc_dword_t event_state;
-  pcsc_dword_t atrlen;
-  unsigned char atr[33];
-};
-
-#ifdef __APPLE__
-#pragma pack()
-#endif
-
-typedef struct pcsc_readerstate_s *pcsc_readerstate_t;
-
-
-static int driver_is_open;     /* True if the PC/SC driver has been
-                                  initialzied and is ready for
-                                  operations.  The following variables
-                                  are then valid. */
-static long pcsc_context;  /* The current PC/CS context. */
-static char *current_rdrname;
-static long pcsc_card;
-static pcsc_dword_t pcsc_protocol;
-static unsigned char current_atr[33];
-static size_t current_atrlen;
-
-long (* pcsc_establish_context) (pcsc_dword_t scope,
-                                 const void *reserved1,
-                                 const void *reserved2,
-                                 long *r_context);
-long (* pcsc_release_context) (long context);
-long (* pcsc_list_readers) (long context,
-                            const char *groups,
-                            char *readers, pcsc_dword_t *readerslen);
-long (* pcsc_get_status_change) (long context,
-                                 pcsc_dword_t timeout,
-                                 pcsc_readerstate_t readerstates,
-                                 pcsc_dword_t nreaderstates);
-long (* pcsc_connect) (long context,
-                       const char *reader,
-                       pcsc_dword_t share_mode,
-                       pcsc_dword_t preferred_protocols,
-                       long *r_card,
-                       pcsc_dword_t *r_active_protocol);
-long (* pcsc_reconnect) (long card,
-                         pcsc_dword_t share_mode,
-                         pcsc_dword_t preferred_protocols,
-                         pcsc_dword_t initialization,
-                         pcsc_dword_t *r_active_protocol);
-long (* pcsc_disconnect) (long card,
-                          pcsc_dword_t disposition);
-long (* pcsc_status) (long card,
-                      char *reader, pcsc_dword_t *readerlen,
-                      pcsc_dword_t *r_state,
-                      pcsc_dword_t *r_protocol,
-                      unsigned char *atr, pcsc_dword_t *atrlen);
-long (* pcsc_begin_transaction) (long card);
-long (* pcsc_end_transaction) (long card,
-                               pcsc_dword_t disposition);
-long (* pcsc_transmit) (long card,
-                        const pcsc_io_request_t send_pci,
-                        const unsigned char *send_buffer,
-                        pcsc_dword_t send_len,
-                        pcsc_io_request_t recv_pci,
-                        unsigned char *recv_buffer,
-                        pcsc_dword_t *recv_len);
-long (* pcsc_set_timeout) (long context,
-                           pcsc_dword_t timeout);
-long (* pcsc_control) (long card,
-                       pcsc_dword_t control_code,
-                       const void *send_buffer,
-                       pcsc_dword_t send_len,
-                       void *recv_buffer,
-                       pcsc_dword_t recv_len,
-                       pcsc_dword_t *bytes_returned);
-
-
-
-static void
-bad_request (const char *type)
-{
-  fprintf (stderr, PGM ": bad '%s' request\n", type);
-  exit (1);
-}
-
-static void
-request_failed (int err)
-{
-  if (!err)
-    err = -1;
-
-  putchar (0x81); /* Simple error/success response. */
-
-  putchar (0);
-  putchar (0);
-  putchar (0);
-  putchar (4);
-
-  putchar ((err >> 24) & 0xff);
-  putchar ((err >> 16) & 0xff);
-  putchar ((err >>  8) & 0xff);
-  putchar ((err      ) & 0xff);
-
-  fflush (stdout);
-}
-
-
-static void
-request_succeeded (const void *buffer, size_t buflen)
-{
-  size_t len;
-
-  putchar (0x81); /* Simple error/success response. */
-
-  len = 4 + buflen;
-  putchar ((len >> 24) & 0xff);
-  putchar ((len >> 16) & 0xff);
-  putchar ((len >>  8) & 0xff);
-  putchar ((len      ) & 0xff);
-
-  /* Error code. */
-  putchar (0);
-  putchar (0);
-  putchar (0);
-  putchar (0);
-
-  /* Optional reponse string. */
-  if (buffer)
-    fwrite (buffer, buflen, 1, stdout);
-
-  fflush (stdout);
-}
-
-
-
-static unsigned long
-read_32 (FILE *fp)
-{
-  int c1, c2, c3, c4;
-
-  c1 = getc (fp);
-  c2 = getc (fp);
-  c3 = getc (fp);
-  c4 = getc (fp);
-  if (c1 == EOF || c2 == EOF || c3 == EOF || c4 == EOF)
-    {
-      fprintf (stderr, PGM ": premature EOF while parsing request\n");
-      exit (1);
-    }
-  return (c1 << 24) | (c2 << 16) | (c3 << 8) | c4;
-}
-
-
-
-static const char *
-pcsc_error_string (long err)
-{
-  const char *s;
-
-  if (!err)
-    return "okay";
-  if ((err & 0x80100000) != 0x80100000)
-    return "invalid PC/SC error code";
-  err &= 0xffff;
-  switch (err)
-    {
-    case 0x0002: s = "cancelled"; break;
-    case 0x000e: s = "can't dispose"; break;
-    case 0x0008: s = "insufficient buffer"; break;
-    case 0x0015: s = "invalid ATR"; break;
-    case 0x0003: s = "invalid handle"; break;
-    case 0x0004: s = "invalid parameter"; break;
-    case 0x0005: s = "invalid target"; break;
-    case 0x0011: s = "invalid value"; break;
-    case 0x0006: s = "no memory"; break;
-    case 0x0013: s = "comm error"; break;
-    case 0x0001: s = "internal error"; break;
-    case 0x0014: s = "unknown error"; break;
-    case 0x0007: s = "waited too long"; break;
-    case 0x0009: s = "unknown reader"; break;
-    case 0x000a: s = "timeout"; break;
-    case 0x000b: s = "sharing violation"; break;
-    case 0x000c: s = "no smartcard"; break;
-    case 0x000d: s = "unknown card"; break;
-    case 0x000f: s = "proto mismatch"; break;
-    case 0x0010: s = "not ready"; break;
-    case 0x0012: s = "system cancelled"; break;
-    case 0x0016: s = "not transacted"; break;
-    case 0x0017: s = "reader unavailable"; break;
-    case 0x0065: s = "unsupported card"; break;
-    case 0x0066: s = "unresponsive card"; break;
-    case 0x0067: s = "unpowered card"; break;
-    case 0x0068: s = "reset card"; break;
-    case 0x0069: s = "removed card"; break;
-    case 0x006a: s = "inserted card"; break;
-    case 0x001f: s = "unsupported feature"; break;
-    case 0x0019: s = "PCI too small"; break;
-    case 0x001a: s = "reader unsupported"; break;
-    case 0x001b: s = "duplicate reader"; break;
-    case 0x001c: s = "card unsupported"; break;
-    case 0x001d: s = "no service"; break;
-    case 0x001e: s = "service stopped"; break;
-    default:     s = "unknown PC/SC error code"; break;
-    }
-  return s;
-}
-
-static void
-load_pcsc_driver (const char *libname)
-{
-  void *handle;
-
-  handle = dlopen (libname, RTLD_LAZY);
-  if (!handle)
-    {
-      fprintf (stderr, PGM ": failed to open driver '%s': %s",
-               libname, dlerror ());
-      exit (1);
-    }
-
-  pcsc_establish_context = dlsym (handle, "SCardEstablishContext");
-  pcsc_release_context   = dlsym (handle, "SCardReleaseContext");
-  pcsc_list_readers      = dlsym (handle, "SCardListReaders");
-  pcsc_get_status_change = dlsym (handle, "SCardGetStatusChange");
-  pcsc_connect           = dlsym (handle, "SCardConnect");
-  pcsc_reconnect         = dlsym (handle, "SCardReconnect");
-  pcsc_disconnect        = dlsym (handle, "SCardDisconnect");
-  pcsc_status            = dlsym (handle, "SCardStatus");
-  pcsc_begin_transaction = dlsym (handle, "SCardBeginTransaction");
-  pcsc_end_transaction   = dlsym (handle, "SCardEndTransaction");
-  pcsc_transmit          = dlsym (handle, "SCardTransmit");
-  pcsc_set_timeout       = dlsym (handle, "SCardSetTimeout");
-  pcsc_control           = dlsym (handle, "SCardControl");
-
-  if (!pcsc_establish_context
-      || !pcsc_release_context
-      || !pcsc_list_readers
-      || !pcsc_get_status_change
-      || !pcsc_connect
-      || !pcsc_reconnect
-      || !pcsc_disconnect
-      || !pcsc_status
-      || !pcsc_begin_transaction
-      || !pcsc_end_transaction
-      || !pcsc_transmit
-      || !pcsc_control
-      /* || !pcsc_set_timeout */)
-    {
-      /* Note that set_timeout is currently not used and also not
-         available under Windows. */
-      fprintf (stderr,
-               "apdu_open_reader: invalid PC/SC driver "
-               "(%d%d%d%d%d%d%d%d%d%d%d%d%d)\n",
-               !!pcsc_establish_context,
-               !!pcsc_release_context,
-               !!pcsc_list_readers,
-               !!pcsc_get_status_change,
-               !!pcsc_connect,
-               !!pcsc_reconnect,
-               !!pcsc_disconnect,
-               !!pcsc_status,
-               !!pcsc_begin_transaction,
-               !!pcsc_end_transaction,
-               !!pcsc_transmit,
-               !!pcsc_set_timeout,
-               !!pcsc_control );
-      dlclose (handle);
-      exit (1);
-    }
-}
-
-
-
-
-/* Handle a open request.  The argument is expected to be a string
-   with the port identification.  ARGBUF is always guaranteed to be
-   terminted by a 0 which is not counted in ARGLEN.  We may modifiy
-   ARGBUF. */
-static void
-handle_open (unsigned char *argbuf, size_t arglen)
-{
-  long err;
-  const char * portstr;
-  char *list = NULL;
-  pcsc_dword_t nreader, atrlen;
-  char *p;
-  pcsc_dword_t card_state, card_protocol;
-  unsigned char atr[33];
-
-  /* Make sure there is only the port string */
-  if (arglen != strlen ((char*)argbuf))
-    bad_request ("OPEN");
-  portstr = (char*)argbuf;
-
-  if (driver_is_open)
-    {
-      fprintf (stderr, PGM ": PC/SC has already been opened\n");
-      request_failed (-1);
-      return;
-    }
-
-  err = pcsc_establish_context (PCSC_SCOPE_SYSTEM, NULL, NULL, &pcsc_context);
-  if (err)
-    {
-      fprintf (stderr, PGM": pcsc_establish_context failed: %s (0x%lx)\n",
-               pcsc_error_string (err), err);
-      request_failed (err);
-      return;
-    }
-
-  err = pcsc_list_readers (pcsc_context, NULL, NULL, &nreader);
-  if (!err)
-    {
-      list = malloc (nreader+1); /* Better add 1 for safety reasons. */
-      if (!list)
-        {
-          fprintf (stderr, PGM": error allocating memory for reader list\n");
-          exit (1);
-        }
-      err = pcsc_list_readers (pcsc_context, NULL, list, &nreader);
-    }
-  if (err)
-    {
-      fprintf (stderr, PGM": pcsc_list_readers failed: %s (0x%lx)\n",
-               pcsc_error_string (err), err);
-      pcsc_release_context (pcsc_context);
-      free (list);
-      request_failed (err);
-      return;
-    }
-
-  p = list;
-  while (nreader)
-    {
-      if (!*p && !p[1])
-        break;
-      fprintf (stderr, PGM": detected reader '%s'\n", p);
-      if (nreader < (strlen (p)+1))
-        {
-          fprintf (stderr, PGM": invalid response from pcsc_list_readers\n");
-          break;
-        }
-      nreader -= strlen (p)+1;
-      p += strlen (p) + 1;
-    }
-
-  current_rdrname = malloc (strlen (portstr && *portstr? portstr:list)+1);
-  if (!current_rdrname)
-    {
-      fprintf (stderr, PGM": error allocating memory for reader name\n");
-      exit (1);
-    }
-  strcpy (current_rdrname, portstr && *portstr? portstr:list);
-  free (list);
-
-  err = pcsc_connect (pcsc_context,
-                      current_rdrname,
-                      PCSC_SHARE_EXCLUSIVE,
-                      PCSC_PROTOCOL_T0|PCSC_PROTOCOL_T1,
-                      &pcsc_card,
-                      &pcsc_protocol);
-  if (err == 0x8010000c) /* No smartcard.  */
-    {
-      pcsc_card = 0;
-    }
-  else if (err)
-    {
-      fprintf (stderr, PGM": pcsc_connect failed: %s (0x%lx)\n",
-               pcsc_error_string (err), err);
-      pcsc_release_context (pcsc_context);
-      free (current_rdrname);
-      current_rdrname = NULL;
-      pcsc_card = 0;
-      pcsc_protocol = 0;
-      request_failed (err);
-      return;
-    }
-
-  current_atrlen = 0;
-  if (!err)
-    {
-      char reader[250];
-      pcsc_dword_t readerlen;
-
-      atrlen = 33;
-      readerlen = sizeof reader -1;
-      err = pcsc_status (pcsc_card,
-                         reader, &readerlen,
-                         &card_state, &card_protocol,
-                         atr, &atrlen);
-      if (err)
-        fprintf (stderr, PGM": pcsc_status failed: %s (0x%lx)\n",
-                 pcsc_error_string (err), err);
-      else
-        {
-          if (atrlen >= sizeof atr || atrlen >= sizeof current_atr)
-            {
-              fprintf (stderr, PGM": ATR returned by pcsc_status"
-                       " is too large\n");
-              exit (4);
-            }
-          memcpy (current_atr, atr, atrlen);
-          current_atrlen = atrlen;
-        }
-    }
-
-  driver_is_open = 1;
-  request_succeeded (current_atr, current_atrlen);
-}
-
-
-
-/* Handle a close request.  We expect no arguments.  We may modifiy
-   ARGBUF. */
-static void
-handle_close (unsigned char *argbuf, size_t arglen)
-{
-  (void)argbuf;
-  (void)arglen;
-
-  if (!driver_is_open)
-    {
-      fprintf (stderr, PGM ": PC/SC has not yet been opened\n");
-      request_failed (-1);
-      return;
-    }
-
-  free (current_rdrname);
-  current_rdrname = NULL;
-  pcsc_release_context (pcsc_context);
-  pcsc_card = 0;
-  pcsc_protocol = 0;
-
-  request_succeeded (NULL, 0);
-}
-
-
-
-/* Handle a status request.  We expect no arguments.  We may modifiy
-   ARGBUF. */
-static void
-handle_status (unsigned char *argbuf, size_t arglen)
-{
-  long err;
-  struct pcsc_readerstate_s rdrstates[1];
-  int status;
-  unsigned char buf[20];
-
-  (void)argbuf;
-  (void)arglen;
-
-  if (!driver_is_open)
-    {
-      fprintf (stderr, PGM ": PC/SC has not yet been opened\n");
-      request_failed (-1);
-      return;
-    }
-
-  memset (rdrstates, 0, sizeof *rdrstates);
-  rdrstates[0].reader = current_rdrname;
-  rdrstates[0].current_state = PCSC_STATE_UNAWARE;
-  err = pcsc_get_status_change (pcsc_context,
-                                0,
-                                rdrstates, 1);
-  if (err == 0x8010000a) /* Timeout.  */
-    err = 0;
-  if (err)
-    {
-      fprintf (stderr, PGM": pcsc_get_status_change failed: %s (0x%lx)\n",
-               pcsc_error_string (err), err);
-      request_failed (err);
-      return;
-    }
-
-  status = 0;
-  if ( !(rdrstates[0].event_state & PCSC_STATE_UNKNOWN) )
-    {
-      if ( (rdrstates[0].event_state & PCSC_STATE_PRESENT) )
-       {
-         status |= 2;
-         if ( !(rdrstates[0].event_state & PCSC_STATE_MUTE) )
-           status |= 4;
-       }
-      /* We indicate a useful card if it is not in use by another
-         application.  This is because we only use exclusive access
-         mode.  */
-      if ( (status & 6) == 6
-           && !(rdrstates[0].event_state & PCSC_STATE_INUSE) )
-        status |= 1;
-    }
-
-  /* First word is identical to the one used by apdu.c. */
-  buf[0] = 0;
-  buf[1] = 0;
-  buf[2] = 0;
-  buf[3] = status;
-  /* The second word is the native PCSC state.  */
-  buf[4] = (rdrstates[0].event_state >> 24);
-  buf[5] = (rdrstates[0].event_state >> 16);
-  buf[6] = (rdrstates[0].event_state >>  8);
-  buf[7] = (rdrstates[0].event_state >>  0);
-  /* The third word is the protocol. */
-  buf[8]  = (pcsc_protocol >> 24);
-  buf[9]  = (pcsc_protocol >> 16);
-  buf[10] = (pcsc_protocol >> 8);
-  buf[11] = (pcsc_protocol);
-
-  request_succeeded (buf, 8);
-}
-
-
-/* Handle a reset request.  We expect no arguments.  We may modifiy
-   ARGBUF. */
-static void
-handle_reset (unsigned char *argbuf, size_t arglen)
-{
-  long err;
-  char reader[250];
-  pcsc_dword_t nreader, atrlen;
-  pcsc_dword_t card_state, card_protocol;
-
-  (void)argbuf;
-  (void)arglen;
-
-  if (!driver_is_open)
-    {
-      fprintf (stderr, PGM ": PC/SC has not yet been opened\n");
-      request_failed (-1);
-      return;
-    }
-
-  if (pcsc_card)
-    {
-      err = pcsc_disconnect (pcsc_card, PCSC_LEAVE_CARD);
-      if (err == 0x80100003)  /* Invalid handle.  (already disconnected) */
-        err = 0;
-      if (err)
-        {
-          fprintf (stderr, PGM": pcsc_disconnect failed: %s (0x%lx)\n",
-                     pcsc_error_string (err), err);
-          request_failed (err);
-          return;
-        }
-      pcsc_card = 0;
-    }
-
-  err = pcsc_connect (pcsc_context,
-                      current_rdrname,
-                      PCSC_SHARE_EXCLUSIVE,
-                      PCSC_PROTOCOL_T0|PCSC_PROTOCOL_T1,
-                      &pcsc_card,
-                      &pcsc_protocol);
-  if (err)
-    {
-      fprintf (stderr, PGM": pcsc_connect failed: %s (0x%lx)\n",
-               pcsc_error_string (err), err);
-      pcsc_card = 0;
-      request_failed (err);
-      return;
-    }
-
-
-  atrlen = 33;
-  nreader = sizeof reader - 1;
-  err = pcsc_status (pcsc_card,
-                     reader, &nreader,
-                     &card_state, &card_protocol,
-                     current_atr, &atrlen);
-  if (err)
-    {
-      fprintf (stderr, PGM": pcsc_status failed: %s (0x%lx)\n",
-               pcsc_error_string (err), err);
-      current_atrlen = 0;
-      request_failed (err);
-      return;
-    }
-
-  request_succeeded (current_atr, current_atrlen);
-}
-
-
-
-/* Handle a transmit request.  The argument is expected to be a buffer
-   with the APDU.  We may modifiy ARGBUF. */
-static void
-handle_transmit (unsigned char *argbuf, size_t arglen)
-{
-  long err;
-  struct pcsc_io_request_s send_pci;
-  pcsc_dword_t recv_len;
-  unsigned char buffer[4096];
-
-  /* The apdu should at least be one byte. */
-  if (!arglen)
-    bad_request ("TRANSMIT");
-
-  if (!driver_is_open)
-    {
-      fprintf (stderr, PGM ": PC/SC has not yet been opened\n");
-      request_failed (-1);
-      return;
-    }
-  if ((pcsc_protocol & PCSC_PROTOCOL_T1))
-    send_pci.protocol = PCSC_PROTOCOL_T1;
-  else
-    send_pci.protocol = PCSC_PROTOCOL_T0;
-  send_pci.pci_len = sizeof send_pci;
-  recv_len = sizeof (buffer);
-  err = pcsc_transmit (pcsc_card, &send_pci, argbuf, arglen,
-                       NULL, buffer, &recv_len);
-  if (err)
-    {
-      if (verbose)
-        fprintf (stderr, PGM": pcsc_transmit failed: %s (0x%lx)\n",
-                 pcsc_error_string (err), err);
-      request_failed (err);
-      return;
-    }
-  request_succeeded (buffer, recv_len);
-}
-
-
-/* Handle a control request.  The argument is expected to be a buffer
-   which contains CONTROL_CODE (4-byte) and INPUT_BYTES.
- */
-static void
-handle_control (unsigned char *argbuf, size_t arglen)
-{
-  long err;
-  pcsc_dword_t ioctl_code;
-  pcsc_dword_t recv_len = 1024;
-  unsigned char buffer[1024];
-
-  if (arglen < 4)
-    bad_request ("CONTROL");
-
-  ioctl_code = (argbuf[0] << 24) | (argbuf[1] << 16) | (argbuf[2] << 8) | argbuf[3];
-  argbuf += 4;
-  arglen -= 4;
-
-  recv_len = sizeof (buffer);
-  err = pcsc_control (pcsc_card, ioctl_code, argbuf, arglen,
-                      buffer, recv_len, &recv_len);
-  if (err)
-    {
-      if (verbose)
-        fprintf (stderr, PGM": pcsc_control failed: %s (0x%lx)\n",
-                 pcsc_error_string (err), err);
-      request_failed (err);
-      return;
-    }
-  request_succeeded (buffer, recv_len);
-}
-
-
-static void
-print_version (int with_help)
-{
-  fputs (MYVERSION_LINE "\n"
-         "Copyright (C) 2004 Free Software Foundation, Inc.\n"
-         "This program comes with ABSOLUTELY NO WARRANTY.\n"
-         "This is free software, and you are welcome to redistribute it\n"
-         "under certain conditions. See the file COPYING for details.\n",
-         stdout);
-
-  if (with_help)
-    fputs ("\n"
-          "Usage: " PGM " [OPTIONS] API-NUMBER [LIBNAME]\n"
-          "Helper to connect scdaemon to the PC/SC library\n"
-          "\n"
-          "  --verbose   enable extra informational output\n"
-          "  --version   print version of the program and exit\n"
-          "  --help      display this help and exit\n"
-          BUGREPORT_LINE, stdout );
-
-  exit (0);
-}
-
-
-int
-main (int argc, char **argv)
-{
-  int last_argc = -1;
-  int api_number = 0;
-  int c;
-
-  if (argc)
-    {
-      argc--; argv++;
-    }
-  while (argc && last_argc != argc )
-    {
-      last_argc = argc;
-      if (!strcmp (*argv, "--"))
-        {
-          argc--; argv++;
-          break;
-        }
-      else if (!strcmp (*argv, "--version"))
-        print_version (0);
-      else if (!strcmp (*argv, "--help"))
-        print_version (1);
-      else if (!strcmp (*argv, "--verbose"))
-        {
-          verbose = 1;
-          argc--; argv++;
-        }
-    }
-  if (argc != 1 && argc != 2)
-    {
-      fprintf (stderr, "usage: " PGM " API-NUMBER [LIBNAME]\n");
-      exit (1);
-    }
-
-  api_number = atoi (*argv);
-  argv++; argc--;
-  if (api_number != 1)
-    {
-      fprintf (stderr, PGM ": api-number %d is not valid\n", api_number);
-      exit (1);
-    }
-
-  load_pcsc_driver (argc? *argv : DEFAULT_PCSC_DRIVER);
-
-  while ((c = getc (stdin)) != EOF)
-    {
-      size_t arglen;
-      unsigned char argbuffer[2048];
-
-      arglen = read_32 (stdin);
-      if (arglen >= sizeof argbuffer - 1)
-        {
-          fprintf (stderr, PGM ": request too long\n");
-          exit (1);
-        }
-      if (arglen && fread (argbuffer, arglen, 1, stdin) != 1)
-        {
-          fprintf (stderr, PGM ": error reading request: %s\n",
-                   strerror (errno));
-          exit (1);
-        }
-      argbuffer[arglen] = 0;
-      switch (c)
-        {
-        case 1:
-          handle_open (argbuffer, arglen);
-          break;
-
-        case 2:
-          handle_close (argbuffer, arglen);
-          exit (0);
-          break;
-
-        case 3:
-          handle_transmit (argbuffer, arglen);
-          break;
-
-        case 4:
-          handle_status (argbuffer, arglen);
-          break;
-
-        case 5:
-          handle_reset (argbuffer, arglen);
-          break;
-
-        case 6:
-          handle_control (argbuffer, arglen);
-          break;
-
-        default:
-          fprintf (stderr, PGM ": invalid request 0x%02X\n", c);
-          exit (1);
-        }
-    }
-  return 0;
-}
-
-
-
-/*
-Local Variables:
-compile-command: "gcc -Wall -g -o pcsc-wrapper pcsc-wrapper.c -ldl"
-End:
-*/
diff --git a/scd/sc-copykeys.c b/scd/sc-copykeys.c
deleted file mode 100644 (file)
index eb246c4..0000000
+++ /dev/null
@@ -1,715 +0,0 @@
-/* sc-copykeys.c - A tool to store keys on a smartcard.
- *     Copyright (C) 2003 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include "scdaemon.h"
-#include <gcrypt.h>
-
-#include "../common/ttyio.h"
-#include "../common/simple-pwquery.h"
-#include "iso7816.h"
-#include "apdu.h" /* for open_reader */
-#include "atr.h"
-#include "app-common.h"
-
-#define _(a) (a)
-
-
-enum cmd_and_opt_values
-{ oVerbose       = 'v',
-  oReaderPort     = 500,
-  octapiDriver,
-  oDebug,
-  oDebugAll,
-
-aTest };
-
-
-static ARGPARSE_OPTS opts[] = {
-
-  { 301, NULL, 0, "@Options:\n " },
-
-  { oVerbose, "verbose",   0, "verbose" },
-  { oReaderPort, "reader-port", 2, "|N|connect to reader at port N"},
-  { octapiDriver, "ctapi-driver", 2, "NAME|use NAME as ctAPI driver"},
-  { oDebug,    "debug"     ,4|16, "set debugging flags"},
-  { oDebugAll, "debug-all" ,0, "enable full debugging"},
-  {0}
-};
-
-
-static void copykeys (APP app, const char *fname);
-
-
-static const char *
-my_strusage (int level)
-{
-  const char *p;
-  switch (level)
-    {
-    case 11: p = "sc-copykeys (GnuPG)";
-      break;
-    case 13: p = VERSION; break;
-    case 17: p = PRINTABLE_OS_NAME; break;
-    case 19: p = _("Please report bugs to <@EMAIL@>.\n"); break;
-
-    case 1:
-    case 40: p =  _("Usage: sc-copykeys [options] (-h for help)\n");
-      break;
-    case 41: p = _("Syntax: sc-copykeys [options] "
-                   "file-with-key\n"
-                    "Copy keys to a smartcards\n");
-    break;
-
-    default: p = NULL;
-    }
-  return p;
-}
-
-
-int
-main (int argc, char **argv )
-{
-  ARGPARSE_ARGS pargs;
-  int slot, rc;
-  const char *reader_port = NULL;
-  struct app_ctx_s appbuf;
-
-  memset (&appbuf, 0, sizeof appbuf);
-
-  set_strusage (my_strusage);
-  gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
-  log_set_prefix ("sc-copykeys", 1);
-
-  /* check that the libraries are suitable.  Do it here because
-     the option parsing may need services of the library */
-  if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
-    {
-      log_fatal (_("%s is too old (need %s, have %s)\n"), "libgcrypt",
-                 NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
-    }
-
-  setup_libgcrypt_logging ();
-  gcry_control (GCRYCTL_DISABLE_SECMEM, 0); /* FIXME - we want to use it */
-  /* FIXME? gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);*/
-
-  pargs.argc = &argc;
-  pargs.argv = &argv;
-  pargs.flags=  1;  /* do not remove the args */
-  while (arg_parse (&pargs, opts) )
-    {
-      switch (pargs.r_opt)
-        {
-        case oVerbose: opt.verbose++; break;
-        case oDebug: opt.debug |= pargs.r.ret_ulong; break;
-        case oDebugAll: opt.debug = ~0; break;
-        case oReaderPort: reader_port = pargs.r.ret_str; break;
-        case octapiDriver: opt.ctapi_driver = pargs.r.ret_str; break;
-        default : pargs.err = 2; break;
-       }
-    }
-  if (log_get_errorcount(0))
-    exit(2);
-
-  if (argc != 1)
-    usage (1);
-
-  slot = apdu_open_reader (reader_port);
-  if (slot == -1)
-    exit (1);
-  if (apdu_connect (slot))
-    exit (1);
-
-  /* FIXME: Use select_application. */
-  appbuf.slot = slot;
-  rc = app_select_openpgp (&appbuf);
-  if (rc)
-    {
-      log_error ("selecting openpgp failed: %s\n", gpg_strerror (rc));
-      exit (1);
-    }
-  appbuf.initialized = 1;
-  log_info ("openpgp application selected\n");
-
-  copykeys (&appbuf, *argv);
-
-
-  return 0;
-}
-
-
-
-void
-send_status_info (CTRL ctrl, const char *keyword, ...)
-{
-  /* DUMMY */
-}
-
-
-
-static char *
-read_file (const char *fname, size_t *r_length)
-{
-  FILE *fp;
-  struct stat st;
-  char *buf;
-  size_t buflen;
-
-  fp = fname? fopen (fname, "rb") : stdin;
-  if (!fp)
-    {
-      log_error ("can't open '%s': %s\n",
-                 fname? fname: "[stdin]", strerror (errno));
-      return NULL;
-    }
-
-  if (fstat (fileno(fp), &st))
-    {
-      log_error ("can't stat '%s': %s\n",
-                 fname? fname: "[stdin]", strerror (errno));
-      if (fname)
-        fclose (fp);
-      return NULL;
-    }
-
-  buflen = st.st_size;
-  buf = xmalloc (buflen+1);
-  if (fread (buf, buflen, 1, fp) != 1)
-    {
-      log_error ("error reading '%s': %s\n",
-                 fname? fname: "[stdin]", strerror (errno));
-      if (fname)
-        fclose (fp);
-      xfree (buf);
-      return NULL;
-    }
-  if (fname)
-    fclose (fp);
-
-  *r_length = buflen;
-  return buf;
-}
-
-
-static gcry_sexp_t
-read_key (const char *fname)
-{
-  char *buf;
-  size_t buflen;
-  gcry_sexp_t private;
-  int rc;
-
-  buf = read_file (fname, &buflen);
-  if (!buf)
-    return NULL;
-
-  rc = gcry_sexp_new (&private, buf, buflen, 1);
-  if (rc)
-    {
-      log_error ("gcry_sexp_new failed: %s\n", gpg_strerror (rc));
-      return NULL;
-    }
-  xfree (buf);
-
-  return private;
-}
-
-
-
-static gcry_mpi_t *
-sexp_to_kparms (gcry_sexp_t sexp, unsigned long *created)
-{
-  gcry_sexp_t list, l2;
-  const char *name;
-  const char *s;
-  size_t n;
-  int i, idx;
-  const char *elems;
-  gcry_mpi_t *array;
-
-  *created = 0;
-  list = gcry_sexp_find_token (sexp, "private-key", 0 );
-  if(!list)
-    return NULL;
-
-  /* quick hack to get the creation time. */
-  l2 = gcry_sexp_find_token (list, "created", 0);
-  if (l2 && (name = gcry_sexp_nth_data (l2, 1, &n)))
-    {
-      char *tmp = xmalloc (n+1);
-      memcpy (tmp, name, n);
-      tmp[n] = 0;
-      *created = strtoul (tmp, NULL, 10);
-      xfree (tmp);
-    }
-  gcry_sexp_release (l2);
-  l2 = gcry_sexp_cadr (list);
-  gcry_sexp_release (list);
-  list = l2;
-  name = gcry_sexp_nth_data (list, 0, &n);
-  if(!name || n != 3 || memcmp (name, "rsa", 3))
-    {
-      gcry_sexp_release (list);
-      return NULL;
-    }
-
-  /* Parameter names used with RSA. */
-  elems = "nedpqu";
-  array = xcalloc (strlen(elems) + 1, sizeof *array);
-  for (idx=0, s=elems; *s; s++, idx++ )
-    {
-      l2 = gcry_sexp_find_token (list, s, 1);
-      if (!l2)
-        {
-          for (i=0; i<idx; i++)
-            gcry_mpi_release (array[i]);
-          xfree (array);
-          gcry_sexp_release (list);
-          return NULL; /* required parameter not found */
-       }
-      array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
-      gcry_sexp_release (l2);
-      if (!array[idx])
-        {
-          for (i=0; i<idx; i++)
-            gcry_mpi_release (array[i]);
-          xfree (array);
-          gcry_sexp_release (list);
-          return NULL; /* required parameter is invalid */
-       }
-    }
-
-  gcry_sexp_release (list);
-  return array;
-}
-
-
-/* Return true if the SHA1 fingerprint FPR consists only of zeroes. */
-static int
-fpr_is_zero (const char *fpr)
-{
-  int i;
-
-  for (i=0; i < 20 && !fpr[i]; i++)
-    ;
-  return (i == 20);
-}
-
-
-static void
-show_sha1_fpr (const unsigned char *fpr)
-{
-  int i;
-
-  if (fpr)
-    {
-      for (i=0; i < 20 ; i+=2, fpr += 2 )
-        {
-          if (i == 10 )
-            tty_printf (" ");
-          tty_printf (" %02X%02X", *fpr, fpr[1]);
-        }
-    }
-  else
-    tty_printf (" [none]");
-  tty_printf ("\n");
-}
-
-/* Query the card, show a list of already stored keys and ask the user
-   where to store the key.  Returns the key number or 0 for cancel
-   operation. */
-static int
-query_card (APP app)
-{
-  int keyno = 0;
-  char *serialno, *disp_name, *pubkey_url;
-  unsigned char *fpr1, *fpr2, *fpr3;
-
-
-  if (app_openpgp_cardinfo (app,
-                            &serialno,
-                            &disp_name,
-                            &pubkey_url,
-                            &fpr1, &fpr2, &fpr3))
-    return 0;
-
-
-  for (;;)
-    {
-      char *answer;
-
-      tty_printf ("\n");
-
-      tty_printf ("Serial number ....: %s\n",
-                  serialno? serialno : "[none]");
-      tty_printf ("Name of cardholder: %s\n",
-                  disp_name && *disp_name? disp_name : "[not set]");
-      tty_printf ("URL of public key : %s\n",
-                  pubkey_url && *pubkey_url? pubkey_url : "[not set]");
-      tty_printf ("Signature key ....:");
-      show_sha1_fpr (fpr1);
-      tty_printf ("Encryption key....:");
-      show_sha1_fpr (fpr2);
-      tty_printf ("Authentication key:");
-      show_sha1_fpr (fpr3);
-
-      tty_printf ("\n"
-                  "1 - store as signature key and reset usage counter\n"
-                  "2 - store as encryption key\n"
-                  "3 - store as authentication key\n"
-                  "Q - quit\n"
-                  "\n");
-
-      answer = tty_get("Your selection? ");
-      tty_kill_prompt();
-      if (strlen (answer) != 1)
-        ;
-      else if ( *answer == '1' )
-        {
-          if ( (fpr1 && !fpr_is_zero (fpr1)) )
-            {
-              tty_printf ("\n");
-              log_error ("WARNING: signature key does already exists!\n");
-              tty_printf ("\n");
-              if ( tty_get_answer_is_yes ("Replace existing key? ") )
-                {
-                  keyno = 1;
-                  break;
-                }
-            }
-          else
-            {
-              keyno = 1;
-              break;
-            }
-        }
-      else if ( *answer == '2' )
-        {
-          if ( (fpr2 && !fpr_is_zero (fpr2)) )
-            {
-              tty_printf ("\n");
-              log_error ("WARNING: encryption key does already exists!\n");
-              tty_printf ("\n");
-              if ( tty_get_answer_is_yes ("Replace existing key? ") )
-                {
-                  keyno = 2;
-                  break;
-                }
-            }
-          else
-            {
-              keyno = 2;
-              break;
-            }
-        }
-      else if ( *answer == '3' )
-        {
-          if ( (fpr3 && !fpr_is_zero (fpr3)) )
-            {
-              tty_printf ("\n");
-              log_error ("WARNING: authentication key does already exists!\n");
-              tty_printf ("\n");
-              if ( tty_get_answer_is_yes ("Replace existing key? ") )
-                {
-                  keyno = 3;
-                  break;
-                }
-            }
-          else
-            {
-              keyno = 3;
-              break;
-            }
-        }
-      else if ( *answer == 'q' || *answer == 'Q')
-        {
-          keyno = 0;
-          break;
-        }
-    }
-
-  xfree (serialno);
-  xfree (disp_name);
-  xfree (pubkey_url);
-  xfree (fpr1);
-  xfree (fpr2);
-  xfree (fpr3);
-
-  return keyno;
-}
-
-
-/* Callback function to ask for a PIN. */
-static gpg_error_t
-pincb (void *arg, const char *prompt, char **pinvalue)
-{
-  char *pin = xstrdup ("12345678");
-
-/*    pin = simple_pwquery (NULL, NULL, prompt, */
-/*                          "We need the admin's PIN to store the key on the card", */
-/*                          0, NULL); */
-/*    if (!pin) */
-/*      return gpg_error (GPG_ERR_CANCELED); */
-
-
-
-  *pinvalue = pin;
-  return 0;
-}
-
-
-/* This function expects a file (or NULL for stdin) with the secret
-   and public key parameters.  This file should consist of an
-   S-expression as used by gpg-agent. Only the unprotected format is
-   supported.  Example:
-
-   (private-key
-    (rsa
-     (n #00e0ce9..[some bytes not shown]..51#)
-     (e #010001#)
-     (d #046129F..[some bytes not shown]..81#)
-     (p #00e861b..[some bytes not shown]..f1#)
-     (q #00f7a7c..[some bytes not shown]..61#)
-     (u #304559a..[some bytes not shown]..9b#))
-    (uri http://foo.bar x-foo:whatever_you_want))
-
-*/
-static void
-copykeys (APP app, const char *fname)
-{
-  int rc;
-  gcry_sexp_t private;
-  gcry_mpi_t *mpis, rsa_n, rsa_e, rsa_p, rsa_q;
-  unsigned int nbits;
-  size_t n;
-  unsigned char *template, *tp;
-  unsigned char m[128], e[4];
-  size_t mlen, elen;
-  unsigned long creation_date;
-  time_t created_at;
-  int keyno;
-
-  if (!strcmp (fname, "-"))
-    fname = NULL;
-
-  private = read_key (fname);
-  if (!private)
-    exit (1);
-
-  mpis = sexp_to_kparms (private, &creation_date);
-  if (!creation_date)
-    {
-      log_info ("no creation date found - assuming current date\n");
-      created_at = time (NULL);
-    }
-  else
-    created_at = creation_date;
-  gcry_sexp_release (private);
-  if (!mpis)
-    {
-      log_error ("invalid structure of key file or not RSA\n");
-      exit (1);
-    }
-  /* MPIS is now an array with the key parameters as defined by OpenPGP. */
-  rsa_n = mpis[0];
-  rsa_e = mpis[1];
-  gcry_mpi_release (mpis[2]);
-  rsa_p = mpis[3];
-  rsa_q = mpis[4];
-  gcry_mpi_release (mpis[5]);
-  xfree (mpis);
-
-  nbits = gcry_mpi_get_nbits (rsa_e);
-  if (nbits < 2 || nbits > 32)
-    {
-      log_error ("public exponent too large (more than 32 bits)\n");
-      goto failure;
-    }
-  nbits = gcry_mpi_get_nbits (rsa_p);
-  if (nbits != 512)
-    {
-      log_error ("length of first RSA prime is not 512\n");
-      goto failure;
-    }
-  nbits = gcry_mpi_get_nbits (rsa_q);
-  if (nbits != 512)
-    {
-      log_error ("length of second RSA prime is not 512\n");
-      goto failure;
-    }
-
-  nbits = gcry_mpi_get_nbits (rsa_n);
-  if (nbits != 1024)
-    {
-      log_error ("length of RSA modulus is not 1024\n");
-      goto failure;
-    }
-
-  keyno = query_card (app);
-  if (!keyno)
-    goto failure;
-
-  /* Build the private key template as described in section 4.3.3.6 of
-     the specs.
-                   0xC0   <length> public exponent
-                   0xC1   <length> prime p
-                   0xC2   <length> prime q  */
-  template = tp = xmalloc (1+2 + 1+1+4 + 1+1+64 + 1+1+64);
-  *tp++ = 0xC0;
-  *tp++ = 4;
-  rc = gcry_mpi_print (GCRYMPI_FMT_USG, tp, 4, &n, rsa_e);
-  if (rc)
-    {
-      log_error ("mpi_print failed: %s\n", gpg_strerror (rc));
-      goto failure;
-    }
-  assert (n <= 4);
-  memcpy (e, tp, n);
-  elen = n;
-  if (n != 4)
-    {
-      memmove (tp+4-n, tp, 4-n);
-      memset (tp, 0, 4-n);
-    }
-  tp += 4;
-
-  *tp++ = 0xC1;
-  *tp++ = 64;
-  rc = gcry_mpi_print (GCRYMPI_FMT_USG, tp, 64, &n, rsa_p);
-  if (rc)
-    {
-      log_error ("mpi_print failed: %s\n", gpg_strerror (rc));
-      goto failure;
-    }
-  assert (n == 64);
-  tp += 64;
-
-  *tp++ = 0xC2;
-  *tp++ = 64;
-  rc = gcry_mpi_print (GCRYMPI_FMT_USG, tp, 64, &n, rsa_q);
-  if (rc)
-    {
-      log_error ("mpi_print failed: %s\n", gpg_strerror (rc));
-      goto failure;
-    }
-  assert (n == 64);
-  tp += 64;
-  assert (tp - template == 138);
-
-  /* (we need the modulus to calculate the fingerprint) */
-  rc = gcry_mpi_print (GCRYMPI_FMT_USG, m, 128, &n, rsa_n);
-  if (rc)
-    {
-      log_error ("mpi_print failed: %s\n", gpg_strerror (rc));
-      goto failure;
-    }
-  assert (n == 128);
-  mlen = 128;
-
-
-  rc = app_openpgp_storekey (app, keyno,
-                             template, tp - template,
-                             created_at,
-                             m, mlen,
-                             e, elen,
-                             pincb, NULL);
-
-  if (rc)
-    {
-      log_error ("error storing key: %s\n", gpg_strerror (rc));
-      goto failure;
-    }
-  log_info ("key successfully stored\n");
-  {
-    unsigned char *mm, *ee;
-    size_t mmlen, eelen;
-    int i;
-
-    rc = app_openpgp_readkey (app, keyno, &mm, &mmlen, &ee, &eelen);
-    if (rc)
-      {
-        log_error ("error reading key back: %s\n", gpg_strerror (rc));
-        goto failure;
-      }
-
-    /* Strip leading zeroes. */
-    for (i=0; i < mmlen && !mm[i]; i++)
-      ;
-    mmlen -= i;
-    memmove (mm, mm+i, mmlen);
-    for (i=0; i < eelen && !ee[i]; i++)
-      ;
-    eelen -= i;
-    memmove (ee, ee+i, eelen);
-
-    if (eelen != elen || mmlen != mlen)
-      {
-        log_error ("key parameter length mismatch (n=%u/%u, e=%u/%u)\n",
-                   (unsigned int)mlen, (unsigned int)mmlen,
-                   (unsigned int)elen, (unsigned int)eelen);
-        xfree (mm);
-        xfree (ee);
-        goto failure;
-      }
-
-    if (memcmp (m, mm, mlen))
-      {
-        log_error ("key parameter n mismatch\n");
-        log_printhex ("original n: ", m, mlen);
-        log_printhex ("  copied n: ", mm, mlen);
-        xfree (mm);
-        xfree (ee);
-        goto failure;
-      }
-    if (memcmp (e, ee, elen))
-      {
-        log_error ("key parameter e mismatch\n");
-        log_printhex ("original e: ", e, elen);
-        log_printhex ("  copied e: ", ee, elen);
-        xfree (mm);
-        xfree (ee);
-        goto failure;
-      }
-    xfree (mm);
-    xfree (ee);
-  }
-
-
-  gcry_mpi_release (rsa_e);
-  gcry_mpi_release (rsa_p);
-  gcry_mpi_release (rsa_q);
-  gcry_mpi_release (rsa_n);
-  return;
-
- failure:
-  gcry_mpi_release (rsa_e);
-  gcry_mpi_release (rsa_p);
-  gcry_mpi_release (rsa_q);
-  gcry_mpi_release (rsa_n);
-  exit (1);
-}