aboutsummaryrefslogtreecommitdiffstats
path: root/scd
diff options
context:
space:
mode:
Diffstat (limited to 'scd')
-rw-r--r--scd/ChangeLog22
-rw-r--r--scd/Makefile.am38
-rw-r--r--scd/apdu.c253
-rw-r--r--scd/apdu.h31
-rw-r--r--scd/card-common.h2
-rw-r--r--scd/card-dinsig.c20
-rw-r--r--scd/card-p15.c52
-rw-r--r--scd/card.c98
-rw-r--r--scd/command.c14
-rw-r--r--scd/scdaemon.c12
-rw-r--r--scd/scdaemon.h20
11 files changed, 455 insertions, 107 deletions
diff --git a/scd/ChangeLog b/scd/ChangeLog
index 807f96888..2ed774f21 100644
--- a/scd/ChangeLog
+++ b/scd/ChangeLog
@@ -1,3 +1,25 @@
+2003-06-03 Werner Koch <[email protected]>
+
+ Changed all error codes in all files to the new libgpg-error scheme.
+
+ * scdaemon.h: Include gpg-error.h and errno.h
+ * card.c (map_sc_err): Use unknown for the error source.
+ * Makefile.am: Link with libgpg-error
+
+2003-05-14 Werner Koch <[email protected]>
+
+ * atr.c, atr.h: New.
+ * sc-investigate.c: Dump the ATR in a human readable format.
+
+2003-05-08 Werner Koch <[email protected]>
+
+ * scdaemon.h (DBG_CARD_IO_VALUE): New.
+
+ * sc-investigate.c: New.
+ * scdaemon.c (main): Removed --print-atr option.
+
+ * iso7816.c, iso7816.h, app-openpgp.c: New.
+
2003-04-29 Werner Koch <[email protected]>
* scdaemon.c: New options --print-atr and --reader-port
diff --git a/scd/Makefile.am b/scd/Makefile.am
index 05f774afb..41353836f 100644
--- a/scd/Makefile.am
+++ b/scd/Makefile.am
@@ -1,4 +1,4 @@
-# Copyright (C) 2002 Free Software Foundation, Inc.
+# Copyright (C) 2002, 2003 Free Software Foundation, Inc.
#
# This file is part of GnuPG.
#
@@ -21,7 +21,7 @@
localedir = $(datadir)/locale
INCLUDES = -I../intl -DLOCALEDIR=\"$(localedir)\"
-bin_PROGRAMS = scdaemon
+bin_PROGRAMS = scdaemon sc-investigate sc-genkey
AM_CPPFLAGS = -I$(top_srcdir)/common $(OPENSC_CFLAGS) $(LIBGCRYPT_CFLAGS) \
$(KSBA_CFLAGS) $(LIBASSUAN_CFLAGS)
@@ -31,7 +31,37 @@ scdaemon_SOURCES = \
command.c card.c \
card-common.h \
card-p15.c card-dinsig.c \
- apdu.c apdu.h
+ apdu.c apdu.h \
+ iso7816.c iso7816.h \
+ app-openpgp.c
scdaemon_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a \
- $(OPENSC_LIBS) $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(LIBASSUAN_LIBS) -ldl
+ $(OPENSC_LIBS) $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(LIBASSUAN_LIBS) -lgpg-error -ldl
+
+sc_investigate_SOURCES = \
+ sc-investigate.c scdaemon.h \
+ apdu.c apdu.h \
+ iso7816.c iso7816.h \
+ app-openpgp.c \
+ atr.c atr.h
+
+sc_investigate_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a \
+ $(LIBGCRYPT_LIBS) -lgpg-error -ldl
+
+sc_genkey_SOURCES = \
+ sc-genkey.c scdaemon.h \
+ apdu.c apdu.h \
+ iso7816.c iso7816.h \
+ app-openpgp.c \
+ atr.c atr.h
+
+sc_genkey_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a \
+ $(LIBGCRYPT_LIBS) -lgpg-error -ldl
+
+
+
+
+
+
+
+
diff --git a/scd/apdu.c b/scd/apdu.c
index 8fa531926..63dfa0684 100644
--- a/scd/apdu.c
+++ b/scd/apdu.c
@@ -24,6 +24,7 @@
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
+#include <assert.h>
#include "scdaemon.h"
#include "apdu.h"
@@ -243,6 +244,31 @@ open_ct_reader (int port)
}
+/* Actuall send the APDU of length APDULEN to SLOT and return a
+ maximum of *BUFLEN data in BUFFER, the actual retruned size will be
+ set to BUFLEN. Returns: CT API error code. */
+static int
+ct_send_apdu (int slot, unsigned char *apdu, size_t apdulen,
+ unsigned char *buffer, size_t *buflen)
+{
+ int rc;
+ unsigned char dad[1], sad[1];
+ unsigned short ctbuflen;
+
+ dad[0] = 0; /* Destination address: Card. */
+ sad[0] = 2; /* Source address: Host. */
+ ctbuflen = *buflen;
+ if (DBG_CARD_IO)
+ log_printhex (" CT_data:", apdu, apdulen);
+ rc = CT_data (slot, dad, sad, apdulen, apdu, &ctbuflen, buffer);
+ *buflen = ctbuflen;
+
+ /* FIXME: map the errorcodes to GNUPG ones, so that they can be
+ shared between CTAPI and PCSC. */
+ return rc;
+}
+
+
#endif /*HAVE_CTAPI*/
@@ -292,8 +318,235 @@ apdu_open_reader (int port)
}
+unsigned char *
+apdu_get_atr (int slot, size_t *atrlen)
+{
+ char *buf;
+
+ if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
+ return NULL;
+
+ buf = xtrymalloc (reader_table[slot].atrlen);
+ if (!buf)
+ return NULL;
+ memcpy (buf, reader_table[slot].atr, reader_table[slot].atrlen);
+ *atrlen = reader_table[slot].atrlen;
+ return buf;
+}
+
+
+static const char *
+error_string (int slot, int rc)
+{
+#ifdef HAVE_CTAPI
+ return ct_error_string (rc);
+#elif defined(HAVE_PCSC)
+ return "?";
+#else
+ return "?";
+#endif
+}
+
+
+/* Dispatcher for the actual send_apdu fucntion. */
+static int
+send_apdu (int slot, unsigned char *apdu, size_t apdulen,
+ unsigned char *buffer, size_t *buflen)
+{
+#ifdef HAVE_CTAPI
+ return ct_send_apdu (slot, apdu, apdulen, buffer, buflen);
+#elif defined(HAVE_PCSC)
+ return -1;
+#else
+ return -1;
+#endif
+}
+
+/* Send an APDU to the card in SLOT. The APDU is created from all
+ given parameters: CLASS, INS, P0, P1, LC, DATA, LE. A value of -1
+ for LC won't sent this field and the data field; in this case DATA
+ must also be passed as NULL. The return value is the status word
+ or -1 for an invalid SLOT or other non card related error. If
+ RETBUF is not NULL, it will receive an allocated buffer with the
+ returned data. The length of that data will be put into
+ *RETBUFLEN. The caller is reposnible for releasing the buffer even
+ in case of errors. */
+int
+apdu_send_le(int slot, int class, int ins, int p0, int p1,
+ int lc, const char *data, int le,
+ unsigned char **retbuf, size_t *retbuflen)
+{
+ unsigned char result[256+10]; /* 10 extra in case of bugs in the driver. */
+ size_t resultlen = 256;
+ unsigned char apdu[5+256+1];
+ size_t apdulen;
+ int rc, sw;
+
+ if (DBG_CARD_IO)
+ log_debug ("send apdu: c=%02X i=%02X p0=%02X p1=%02X lc=%d le=%d\n",
+ class, ins, p0, p1, lc, le);
+
+ if (lc != -1 && (lc > 255 || lc < 0))
+ return SW_WRONG_LENGTH;
+ if (le != -1 && (le > 256 || le < 1))
+ return SW_WRONG_LENGTH;
+ if ((!data && lc != -1) || (data && lc == -1))
+ return -1;
+
+ apdulen = 0;
+ apdu[apdulen++] = class;
+ apdu[apdulen++] = ins;
+ apdu[apdulen++] = p0;
+ apdu[apdulen++] = p1;
+ if (lc != -1)
+ {
+ apdu[apdulen++] = lc;
+ memcpy (apdu+apdulen, data, lc);
+ apdulen += lc;
+ }
+ if (le != -1)
+ apdu[apdulen++] = le; /* Truncation is okay becuase 0 means 256. */
+ assert (sizeof (apdu) >= apdulen);
+ /* As safeguard don't pass any garbage from the stack to the driver. */
+ memset (apdu+apdulen, 0, sizeof (apdu) - apdulen);
+ rc = send_apdu (slot, apdu, apdulen, result, &resultlen);
+ if (rc || resultlen < 2)
+ {
+ log_error ("apdu_send_simple(%d) failed: %s\n",
+ slot, error_string (slot, rc));
+ return -1;
+ }
+ sw = (result[resultlen-2] << 8) | result[resultlen-1];
+ /* store away the returned data but strip the statusword. */
+ resultlen -= 2;
+ if (DBG_CARD_IO)
+ {
+ log_debug (" response: sw=%04X datalen=%d\n", sw, resultlen);
+ if ( !retbuf && (sw == SW_SUCCESS || (sw & 0xff00) == SW_MORE_DATA))
+ log_printhex (" dump: ", result, resultlen);
+ }
+
+ if (sw == SW_SUCCESS)
+ {
+ if (retbuf)
+ {
+ *retbuf = xtrymalloc (resultlen? resultlen : 1);
+ if (!*retbuf)
+ return -1; /* fixme: this is actually out of core. */
+ *retbuflen = resultlen;
+ memcpy (*retbuf, result, resultlen);
+ }
+ }
+ else if ((sw & 0xff00) == SW_MORE_DATA)
+ {
+ unsigned char *p = NULL, *tmp;
+ size_t bufsize = 4096;
+ /* It is likely that we need to return much more data, so we
+ start off with a large buffer. */
+ if (retbuf)
+ {
+ *retbuf = p = xtrymalloc (bufsize);
+ if (!*retbuf)
+ return -1; /* fixme: this is actually out of core. */
+ assert (resultlen < bufsize);
+ memcpy (p, result, resultlen);
+ p += resultlen;
+ }
+ do
+ {
+ int len = (sw & 0x00ff);
+
+ log_debug ("apdu_send_simple(%d): %d more bytes available\n",
+ slot, len);
+ apdulen = 0;
+ apdu[apdulen++] = class;
+ apdu[apdulen++] = 0xC0;
+ apdu[apdulen++] = 0;
+ apdu[apdulen++] = 0;
+ apdu[apdulen++] = 64; /* that is 256 bytes for Le */
+ memset (apdu+apdulen, 0, sizeof (apdu) - apdulen);
+ rc = send_apdu (slot, apdu, apdulen, result, &resultlen);
+ if (rc || resultlen < 2)
+ {
+ log_error ("apdu_send_simple(%d) for get response failed: %s\n",
+ slot, error_string (slot, rc));
+ return -1;
+ }
+ sw = (result[resultlen-2] << 8) | result[resultlen-1];
+ resultlen -= 2;
+ if (DBG_CARD_IO)
+ {
+ log_debug (" more: sw=%04X datalen=%d\n", sw, resultlen);
+ if (!retbuf && (sw==SW_SUCCESS || (sw&0xff00)==SW_MORE_DATA))
+ log_printhex (" dump: ", result, resultlen);
+ }
+ if ((sw & 0xff00) == SW_MORE_DATA || sw == SW_SUCCESS)
+ {
+ if (retbuf)
+ {
+ if (p - *retbuf + resultlen > bufsize)
+ {
+ bufsize += resultlen > 4096? resultlen: 4096;
+ tmp = xtryrealloc (*retbuf, bufsize);
+ if (!tmp)
+ return -1; /* fixme: actually this is out of core */
+ p = tmp + (p - *retbuf);
+ *retbuf = tmp;
+ }
+ memcpy (p, result, resultlen);
+ p += resultlen;
+ }
+ }
+ else
+ log_info ("apdu_send_simple(%d) "
+ "got unexpected status %04X from get response\n",
+ slot, sw);
+ }
+ while ((sw & 0xff00) == SW_MORE_DATA);
+
+ if (retbuf)
+ {
+ *retbuflen = p - *retbuf;
+ tmp = xtryrealloc (*retbuf, *retbuflen);
+ if (tmp)
+ *retbuf = tmp;
+ }
+ }
+ if (DBG_CARD_IO && retbuf && sw == SW_SUCCESS)
+ log_printhex (" dump: ", *retbuf, *retbuflen);
+
+ return sw;
+}
+/* Send an APDU to the card in SLOT. The APDU is created from all
+ given parameters: CLASS, INS, P0, P1, LC, DATA. A value of -1 for
+ LC won't sent this field and the data field; in this case DATA must
+ also be passed as NULL. The return value is the status word or -1
+ for an invalid SLOT or other non card related error. If RETBUF is
+ not NULL, it will receive an allocated buffer with the returned
+ data. The length of that data will be put into *RETBUFLEN. The
+ caller is reponsible for releasing the buffer even in case of
+ errors. */
+int
+apdu_send(int slot, int class, int ins, int p0, int p1,
+ int lc, const char *data, unsigned char **retbuf, size_t *retbuflen)
+{
+ return apdu_send_le (slot, class, ins, p0, p1, lc, data, 256,
+ retbuf, retbuflen);
+}
+/* Send an APDU to the card in SLOT. The APDU is created from all
+ given parameters: CLASS, INS, P0, P1, LC, DATA. A value of -1 for
+ LC won't sent this field and the data field; in this case DATA must
+ also be passed as NULL. The return value is the status word or -1
+ for an invalid SLOT or other non card related error. No data will be
+ returned. */
+int
+apdu_send_simple (int slot, int class, int ins, int p0, int p1,
+ int lc, const char *data)
+{
+ return apdu_send (slot, class, ins, p0, p1, lc, data, NULL, NULL);
+}
diff --git a/scd/apdu.h b/scd/apdu.h
index fc10eed69..47fd1a8f6 100644
--- a/scd/apdu.h
+++ b/scd/apdu.h
@@ -1,4 +1,4 @@
-/* apdu.c - ISO 7816 APDU functions and low level I/O
+/* apdu.h - ISO 7816 APDU functions and low level I/O
* Copyright (C) 2003 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
@@ -21,9 +21,38 @@
#ifndef APDU_H
#define APDU_H
+/* ISO 7816 values for the statusword are defined here because they
+ should not be visible to the users of the actual iso command
+ API. */
+enum {
+ SW_MORE_DATA = 0x6100, /* Note: that the low byte must be
+ masked of.*/
+ SW_EEPROM_FAILURE = 0x6581,
+ SW_WRONG_LENGTH = 0x6700,
+ SW_CHV_WRONG = 0x6982,
+ SW_CHV_BLOCKED = 0x6983,
+ SW_USE_CONDITIONS = 0x6985,
+ SW_BAD_PARAMETER = 0x6a80, /* (in the data field) */
+ SW_REF_NOT_FOUND = 0x6a88,
+ SW_BAD_P0_P1 = 0x6b00,
+ SW_INS_NOT_SUP = 0x6d00,
+ SW_CLA_NOT_SUP = 0x6e00,
+ SW_SUCCESS = 0x9000
+};
+int apdu_open_reader (int port);
+unsigned char *apdu_get_atr (int slot, size_t *atrlen);
+
+int apdu_send_simple (int slot, int class, int ins, int p0, int p1,
+ int lc, const char *data);
+int apdu_send (int slot, int class, int ins, int p0, int p1,
+ int lc, const char *data,
+ unsigned char **retbuf, size_t *retbuflen);
+int apdu_send_le (int slot, int class, int ins, int p0, int p1,
+ int lc, const char *data, int le,
+ unsigned char **retbuf, size_t *retbuflen);
#endif /*APDU_H*/
diff --git a/scd/card-common.h b/scd/card-common.h
index 50014cead..7ce2726c3 100644
--- a/scd/card-common.h
+++ b/scd/card-common.h
@@ -59,7 +59,7 @@ struct card_ctx_s {
};
/*-- card.c --*/
-int map_sc_err (int rc);
+gpg_error_t map_sc_err (int rc);
int card_help_get_keygrip (KsbaCert cert, unsigned char *array);
/*-- card-15.c --*/
diff --git a/scd/card-dinsig.c b/scd/card-dinsig.c
index a9437e47c..6262ca3bc 100644
--- a/scd/card-dinsig.c
+++ b/scd/card-dinsig.c
@@ -116,8 +116,9 @@ dinsig_enum_keypairs (CARD card, int idx,
cert = ksba_cert_new ();
if (!cert)
{
+ gpg_error_t tmperr = out_of_core ();
xfree (buf);
- return GNUPG_Out_Of_Core;
+ return tmperr;
}
krc = ksba_cert_init_from_mem (cert, buf, buflen);
@@ -127,13 +128,13 @@ dinsig_enum_keypairs (CARD card, int idx,
log_error ("failed to parse the certificate at idx %d: %s\n",
idx, ksba_strerror (krc));
ksba_cert_release (cert);
- return GNUPG_Card_Error;
+ return gpg_error (GPG_ERR_CARD_ERROR);
}
if (card_help_get_keygrip (cert, keygrip))
{
log_error ("failed to calculate the keygrip at index %d\n", idx);
ksba_cert_release (cert);
- return GNUPG_Card_Error;
+ return gpg_error (GPG_ERR_CARD_ERROR);
}
ksba_cert_release (cert);
@@ -142,7 +143,7 @@ dinsig_enum_keypairs (CARD card, int idx,
{
*keyid = xtrymalloc (17);
if (!*keyid)
- return GNUPG_Out_Of_Core;
+ return out_of_core ();
if (!idx)
strcpy (*keyid, "DINSIG-DF01.C000");
else
@@ -170,7 +171,7 @@ dinsig_read_cert (CARD card, const char *certidstr,
else if (!strcmp (certidstr, "DINSIG-DF01.C200"))
sc_format_path ("3F00DF01C200", &path);
else
- return GNUPG_Invalid_Id;
+ return gpg_error (GPG_ERR_INVALID_ID);
rc = sc_select_file (card->scard, &path, &file);
if (rc)
@@ -183,19 +184,20 @@ dinsig_read_cert (CARD card, const char *certidstr,
{
log_error ("wrong type or structure of certificate EF\n");
sc_file_free (file);
- return GNUPG_Card_Error;
+ return gpg_error (GPG_ERR_CARD_ERROR);
}
if (file->size < 20) /* check against a somewhat arbitrary length */
{
log_error ("certificate EF too short\n");
sc_file_free (file);
- return GNUPG_Card_Error;
+ return gpg_error (GPG_ERR_CARD_ERROR);
}
buf = xtrymalloc (file->size);
if (!buf)
{
+ gpg_error_t tmperr = out_of_core ();
sc_file_free (file);
- return GNUPG_Out_Of_Core;
+ return tmperr;
}
rc = sc_read_binary (card->scard, 0, buf, file->size, 0);
@@ -204,7 +206,7 @@ dinsig_read_cert (CARD card, const char *certidstr,
log_error ("short read on certificate EF\n");
sc_file_free (file);
xfree (buf);
- return GNUPG_Card_Error;
+ return gpg_error (GPG_ERR_CARD_ERROR);
}
sc_file_free (file);
if (rc < 0)
diff --git a/scd/card-p15.c b/scd/card-p15.c
index 7fa2d8fe8..e9050faba 100644
--- a/scd/card-p15.c
+++ b/scd/card-p15.c
@@ -53,7 +53,7 @@ init_private_data (CARD card)
priv = xtrycalloc (1, sizeof *priv);
if (!priv)
- return GNUPG_Out_Of_Core;
+ return out_of_core ();
/* 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
@@ -70,7 +70,7 @@ init_private_data (CARD card)
{
log_error ("private keys enumeration failed: %s\n", sc_strerror (rc));
xfree (priv);
- return GNUPG_Card_Error;
+ return gpg_error (GPG_ERR_CARD_ERROR);
}
priv->n_prkey_rsa_objs = rc;
@@ -82,7 +82,7 @@ init_private_data (CARD card)
{
log_error ("private keys enumeration failed: %s\n", sc_strerror (rc));
xfree (priv);
- return GNUPG_Card_Error;
+ return gpg_error (GPG_ERR_CARD_ERROR);
}
priv->n_cert_objs = rc;
@@ -136,7 +136,7 @@ p15_enum_keypairs (CARD card, int idx,
log_info ("certificate for private key %d not found: %s\n",
idx, sc_strerror (rc));
/* note, that we return the ID anyway */
- rc = GNUPG_Missing_Certificate;
+ rc = gpg_error (GPG_ERR_MISSING_CERTIFICATE);
goto return_keyid;
}
certinfo = tmpobj->data;
@@ -145,14 +145,15 @@ p15_enum_keypairs (CARD card, int idx,
{
log_info ("failed to read certificate for private key %d: %s\n",
idx, sc_strerror (rc));
- return GNUPG_Card_Error;
+ return gpg_error (GPG_ERR_CARD_ERROR);
}
cert = ksba_cert_new ();
if (!cert)
{
+ gpg_error_t tmperr = out_of_core ();
sc_pkcs15_free_certificate (certder);
- return GNUPG_Out_Of_Core;
+ return tmperr;
}
krc = ksba_cert_init_from_mem (cert, certder->data, certder->data_len);
sc_pkcs15_free_certificate (certder);
@@ -161,13 +162,13 @@ p15_enum_keypairs (CARD card, int idx,
log_error ("failed to parse the certificate for private key %d: %s\n",
idx, ksba_strerror (krc));
ksba_cert_release (cert);
- return GNUPG_Card_Error;
+ return gpg_error (GPG_ERR_CARD_ERROR);
}
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 GNUPG_Card_Error;
+ return gpg_error (GPG_ERR_CARD_ERROR);
}
ksba_cert_release (cert);
@@ -180,7 +181,7 @@ p15_enum_keypairs (CARD card, int idx,
*keyid = p = xtrymalloc (9+pinfo->id.len*2+1);
if (!*keyid)
- return GNUPG_Out_Of_Core;
+ return out_of_core ();
p = stpcpy (p, "P15-5015.");
for (i=0; i < pinfo->id.len; i++, p += 2)
sprintf (p, "%02X", pinfo->id.value[i]);
@@ -218,7 +219,7 @@ p15_enum_certs (CARD card, int idx, char **certid, int *type)
*certid = p = xtrymalloc (9+cinfo->id.len*2+1);
if (!*certid)
- return GNUPG_Out_Of_Core;
+ return out_of_core ();
p = stpcpy (p, "P15-5015.");
for (i=0; i < cinfo->id.len; i++, p += 2)
sprintf (p, "%02X", cinfo->id.value[i]);
@@ -251,14 +252,14 @@ idstr_to_id (const char *idstr, struct sc_pkcs15_id *id)
/* For now we only support the standard DF */
if (strncmp (idstr, "P15-5015.", 9) )
- return GNUPG_Invalid_Id;
+ return gpg_error (GPG_ERR_INVALID_ID);
for (s=idstr+9, n=0; hexdigitp (s); s++, n++)
;
if (*s || (n&1))
- return GNUPG_Invalid_Id; /* invalid or odd number of digits */
+ return gpg_error (GPG_ERR_INVALID_ID); /*invalid or odd number of digits*/
n /= 2;
if (!n || n > SC_PKCS15_MAX_ID_SIZE)
- return GNUPG_Invalid_Id; /* empty or too large */
+ return gpg_error (GPG_ERR_INVALID_ID); /* empty or too large */
for (s=idstr+9, n=0; *s; s += 2, n++)
id->value[n] = xtoi_2 (s);
id->len = n;
@@ -278,9 +279,9 @@ p15_read_cert (CARD card, const char *certidstr,
int rc;
if (!card || !certidstr || !cert || !ncert)
- return GNUPG_Invalid_Value;
+ return gpg_error (GPG_ERR_INVALID_VALUE);
if (!card->p15card)
- return GNUPG_No_PKCS15_App;
+ return gpg_error (GPG_ERR_NO_PKCS15_APP);
rc = idstr_to_id (certidstr, &certid);
if (rc)
@@ -299,14 +300,15 @@ p15_read_cert (CARD card, const char *certidstr,
{
log_info ("failed to read certificate '%s': %s\n",
certidstr, sc_strerror (rc));
- return GNUPG_Card_Error;
+ return gpg_error (GPG_ERR_CARD_ERROR);
}
*cert = xtrymalloc (certder->data_len);
if (!*cert)
{
+ gpg_error_t tmperr = out_of_core ();
sc_pkcs15_free_certificate (certder);
- return GNUPG_Out_Of_Core;
+ return tmperr;
}
memcpy (*cert, certder->data, certder->data_len);
*ncert = certder->data_len;
@@ -337,7 +339,7 @@ p15_prepare_key (CARD card, const char *keyidstr,
if (rc < 0)
{
log_error ("private key not found: %s\n", sc_strerror(rc));
- return GNUPG_No_Secret_Key;
+ return gpg_error (GPG_ERR_NO_SECRET_KEY);
}
rc = sc_pkcs15_find_pin_by_auth_id (card->p15card,
@@ -345,7 +347,7 @@ p15_prepare_key (CARD card, const char *keyidstr,
if (rc)
{
log_error ("failed to find PIN by auth ID: %s\n", sc_strerror (rc));
- return GNUPG_Bad_PIN_Method;
+ return gpg_error (GPG_ERR_BAD_PIN_METHOD);
}
pin = pinobj->data;
@@ -365,7 +367,7 @@ p15_prepare_key (CARD card, const char *keyidstr,
if (rc)
{
log_info ("PIN verification failed: %s\n", sc_strerror (rc));
- return GNUPG_Bad_PIN;
+ return gpg_error (GPG_ERR_BAD_PIN);
}
/* fixme: check wheter we need to release KEYOBJ in case of an error */
@@ -389,7 +391,7 @@ p15_sign (CARD card, const char *keyidstr, int hashalgo,
size_t outbuflen;
if (hashalgo != GCRY_MD_SHA1)
- return GNUPG_Unsupported_Algorithm;
+ return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
rc = p15_prepare_key (card, keyidstr, pincb, pincb_arg, &keyobj);
if (rc)
@@ -400,7 +402,7 @@ p15_sign (CARD card, const char *keyidstr, int hashalgo,
outbuflen = 1024;
outbuf = xtrymalloc (outbuflen);
if (!outbuf)
- return GNUPG_Out_Of_Core;
+ return out_of_core ();
rc = sc_pkcs15_compute_signature (card->p15card, keyobj,
cryptflags,
@@ -409,7 +411,7 @@ p15_sign (CARD card, const char *keyidstr, int hashalgo,
if (rc < 0)
{
log_error ("failed to create signature: %s\n", sc_strerror (rc));
- rc = GNUPG_Card_Error;
+ rc = gpg_error (GPG_ERR_CARD_ERROR);
}
else
{
@@ -462,7 +464,7 @@ p15_decipher (CARD card, const char *keyidstr,
outbuflen = indatalen < 256? 256 : indatalen;
outbuf = xtrymalloc (outbuflen);
if (!outbuf)
- return GNUPG_Out_Of_Core;
+ return out_of_core ();
rc = sc_pkcs15_decipher (card->p15card, keyobj,
0,
@@ -471,7 +473,7 @@ p15_decipher (CARD card, const char *keyidstr,
if (rc < 0)
{
log_error ("failed to decipher the data: %s\n", sc_strerror (rc));
- rc = GNUPG_Card_Error;
+ rc = gpg_error (GPG_ERR_CARD_ERROR);
}
else
{
diff --git a/scd/card.c b/scd/card.c
index 998413f7e..682a766f5 100644
--- a/scd/card.c
+++ b/scd/card.c
@@ -34,23 +34,25 @@
#include "card-common.h"
/* Map the SC error codes to the GNUPG ones */
-int
+gpg_error_t
map_sc_err (int rc)
{
+ gpg_err_code_t e;
+
switch (rc)
{
- case 0: rc = 0; break;
+ case 0: e = 0; break;
#ifdef HAVE_OPENSC
- case SC_ERROR_NOT_SUPPORTED: rc = GNUPG_Not_Supported; break;
- case SC_ERROR_PKCS15_APP_NOT_FOUND: rc = GNUPG_No_PKCS15_App; break;
- case SC_ERROR_OUT_OF_MEMORY: rc = GNUPG_Out_Of_Core; break;
- case SC_ERROR_CARD_NOT_PRESENT: rc = GNUPG_Card_Not_Present; break;
- case SC_ERROR_CARD_REMOVED: rc = GNUPG_Card_Removed; break;
- case SC_ERROR_INVALID_CARD: rc = GNUPG_Invalid_Card; break;
+ 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_INVALID_CARD; break;
#endif
- default: rc = GNUPG_Card_Error; break;
+ default: e = GPG_ERR_CARD_ERROR; break;
}
- return rc;
+ return gpg_make_error (GPG_ERR_SOURCE_UNKNOWN, e);
}
/* Get the keygrip from CERT, return 0 on success */
@@ -89,7 +91,7 @@ card_help_get_keygrip (KsbaCert cert, unsigned char *array)
information of the card. Detects whgether a PKCS_15 application is
stored.
- Common errors: GNUPG_Card_Not_Present */
+ Common errors: GPG_ERR_CARD_NOT_PRESENT */
int
card_open (CARD *rcard)
{
@@ -99,7 +101,7 @@ card_open (CARD *rcard)
card = xtrycalloc (1, sizeof *card);
if (!card)
- return GNUPG_Out_Of_Core;
+ return out_of_core ();
card->reader = 0;
rc = sc_establish_context (&card->ctx, "scdaemon");
@@ -112,7 +114,7 @@ card_open (CARD *rcard)
if (card->reader >= card->ctx->reader_count)
{
log_error ("no card reader available\n");
- rc = GNUPG_Card_Error;
+ rc = gpg_error (GPG_ERR_CARD_ERROR);
goto leave;
}
card->ctx->error_file = log_get_stream ();
@@ -121,7 +123,7 @@ card_open (CARD *rcard)
if (sc_detect_card_presence (card->ctx->reader[card->reader], 0) != 1)
{
- rc = GNUPG_Card_Not_Present;
+ rc = gpg_error (GPG_ERR_CARD_NOT_PRESENT);
goto leave;
}
@@ -155,7 +157,7 @@ card_open (CARD *rcard)
return rc;
#else
- return GNUPG_Not_Supported;
+ return gpg_error (GPG_ERR_NOT_SUPPORTED);
#endif
}
@@ -240,7 +242,7 @@ find_iccsn (const unsigned char *buffer, size_t length, char **serial)
s = find_simple_tlv (buffer, length, 0x5A, &n);
if (!s)
- return GNUPG_Card_Error;
+ return gpg_error (GPG_ERR_CARD_ERROR);
length -= s - buffer;
if (n > length)
{
@@ -255,14 +257,16 @@ find_iccsn (const unsigned char *buffer, size_t length, char **serial)
n--;
}
else
- return GNUPG_Card_Error; /* Bad encoding; does not fit into buffer. */
+ return gpg_error (GPG_ERR_CARD_ERROR); /* Bad encoding; does
+ not fit into
+ buffer. */
}
if (!n)
- return GNUPG_Card_Error; /* Well, that is too short. */
+ return gpg_error (GPG_ERR_CARD_ERROR); /* Well, that is too short. */
*serial = p = xtrymalloc (2*n+1);
if (!*serial)
- return GNUPG_Out_Of_Core;
+ return out_of_core ();
for (; n; n--, p += 2, s++)
sprintf (p, "%02X", *s);
*p = 0;
@@ -290,7 +294,7 @@ card_get_serial_and_stamp (CARD card, char **serial, time_t *stamp)
#endif
if (!card || !serial || !stamp)
- return GNUPG_Invalid_Value;
+ return gpg_error (GPG_ERR_INV_VALUE);
*serial = NULL;
*stamp = 0; /* not available */
@@ -328,21 +332,21 @@ card_get_serial_and_stamp (CARD card, char **serial, time_t *stamp)
if (rc)
{
log_error ("sc_select_file failed: %s\n", sc_strerror (rc));
- return GNUPG_Card_Error;
+ return gpg_error (GPG_ERR_CARD_ERROR);
}
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 GNUPG_Card_Error;
+ return gpg_error (GPG_ERR_CARD_ERROR);
}
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 GNUPG_Card_Error;
+ return gpg_error (GPG_ERR_CARD_ERROR);
}
buflen = file->size;
@@ -351,16 +355,16 @@ card_get_serial_and_stamp (CARD card, char **serial, time_t *stamp)
if (rc < 0)
{
log_error ("error reading GDO file: %s\n", sc_strerror (rc));
- return GNUPG_Card_Error;
+ return gpg_error (GPG_ERR_CARD_ERROR);
}
if (rc != buflen)
{
log_error ("short read on GDO file\n");
- return GNUPG_Card_Error;
+ return gpg_error (GPG_ERR_CARD_ERROR);
}
rc = find_iccsn (buf, buflen, serial);
- if (rc == GNUPG_Card_Error)
+ if (gpg_err_code (rc) == GPG_ERR_CARD_ERROR)
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
@@ -376,7 +380,7 @@ card_get_serial_and_stamp (CARD card, char **serial, time_t *stamp)
*serial = NULL;
p = xtrymalloc (strlen (efser) + 7);
if (!p)
- rc = GNUPG_Out_Of_Core;
+ rc = out_of_core ();
else
{
strcpy (p, "FF0100");
@@ -392,7 +396,7 @@ card_get_serial_and_stamp (CARD card, char **serial, time_t *stamp)
{
xfree (*serial);
*serial = NULL;
- rc = GNUPG_Out_Of_Core;
+ rc = out_of_core ();
}
else
{
@@ -404,7 +408,7 @@ card_get_serial_and_stamp (CARD card, char **serial, time_t *stamp)
}
return rc;
#else
- return GNUPG_Not_Supported;
+ return gpg_error (GPG_ERR_NOT_SUPPORTED);
#endif
}
@@ -415,7 +419,7 @@ card_get_serial_and_stamp (CARD card, char **serial, time_t *stamp)
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 GNUPG_Missing_Certificate may be
+ 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.*/
@@ -430,13 +434,13 @@ card_enum_keypairs (CARD card, int idx,
*keyid = NULL;
if (!card || !keygrip)
- return GNUPG_Invalid_Value;
+ return gpg_error (GPG_ERR_INV_VALUE);
if (idx < 0)
- return GNUPG_Invalid_Index;
+ return gpg_error (GPG_ERR_INVALID_INDEX);
if (!card->fnc.initialized)
- return GNUPG_Card_Not_Initialized;
+ return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
if (!card->fnc.enum_keypairs)
- return GNUPG_Unsupported_Operation;
+ 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",
@@ -462,13 +466,13 @@ card_enum_certs (CARD card, int idx, char **certid, int *certtype)
*certid = NULL;
if (!card)
- return GNUPG_Invalid_Value;
+ return gpg_error (GPG_ERR_INV_VALUE);
if (idx < 0)
- return GNUPG_Invalid_Index;
+ return gpg_error (GPG_ERR_INVALID_INDEX);
if (!card->fnc.initialized)
- return GNUPG_Card_Not_Initialized;
+ return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
if (!card->fnc.enum_certs)
- return GNUPG_Unsupported_Operation;
+ 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",
@@ -489,11 +493,11 @@ card_read_cert (CARD card, const char *certidstr,
int rc;
if (!card || !certidstr || !cert || !ncert)
- return GNUPG_Invalid_Value;
+ return gpg_error (GPG_ERR_INV_VALUE);
if (!card->fnc.initialized)
- return GNUPG_Card_Not_Initialized;
+ return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
if (!card->fnc.read_cert)
- return GNUPG_Unsupported_Operation;
+ 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", gnupg_strerror (rc));
@@ -514,11 +518,11 @@ card_sign (CARD card, const char *keyidstr, int hashalgo,
int rc;
if (!card || !indata || !indatalen || !outdata || !outdatalen || !pincb)
- return GNUPG_Invalid_Value;
+ return gpg_error (GPG_ERR_INV_VALUE);
if (!card->fnc.initialized)
- return GNUPG_Card_Not_Initialized;
+ return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
if (!card->fnc.sign)
- return GNUPG_Unsupported_Operation;
+ return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
rc = card->fnc.sign (card, keyidstr, hashalgo,
pincb, pincb_arg,
indata, indatalen,
@@ -542,11 +546,11 @@ card_decipher (CARD card, const char *keyidstr,
int rc;
if (!card || !indata || !indatalen || !outdata || !outdatalen || !pincb)
- return GNUPG_Invalid_Value;
+ return gpg_error (GPG_ERR_INV_VALUE);
if (!card->fnc.initialized)
- return GNUPG_Card_Not_Initialized;
+ return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
if (!card->fnc.decipher)
- return GNUPG_Unsupported_Operation;
+ return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
rc = card->fnc.decipher (card, keyidstr,
pincb, pincb_arg,
indata, indatalen,
diff --git a/scd/command.c b/scd/command.c
index d0bbbc518..329fb4d2f 100644
--- a/scd/command.c
+++ b/scd/command.c
@@ -233,7 +233,7 @@ cmd_learn (ASSUAN_CONTEXT ctx, char *line)
buf = xtrymalloc (40 + 1 + strlen (certid) + 1);
if (!buf)
- rc = GNUPG_Out_Of_Core;
+ rc = out_of_core ();
else
{
sprintf (buf, "%d %s", certtype, certid);
@@ -255,7 +255,7 @@ cmd_learn (ASSUAN_CONTEXT ctx, char *line)
int no_cert = 0;
rc = card_enum_keypairs (ctrl->card_ctx, idx, keygrip, &keyid);
- if (rc == GNUPG_Missing_Certificate && keyid)
+ if (gpg_err_code (rc) == GPG_ERR_MISSING_CERT && keyid)
{
/* this does happen with an incomplete personalized
card; i.e. during the time we have stored the key on the
@@ -271,7 +271,7 @@ cmd_learn (ASSUAN_CONTEXT ctx, char *line)
buf = p = xtrymalloc (40 + 1 + strlen (keyid) + 1);
if (!buf)
- rc = GNUPG_Out_Of_Core;
+ rc = out_of_core ();
else
{
int i;
@@ -358,8 +358,8 @@ cmd_readkey (ASSUAN_CONTEXT ctx, char *line)
kc = ksba_cert_new ();
if (!kc)
{
+ rc = out_of_core ();
xfree (cert);
- rc = GNUPG_Out_Of_Core;
goto leave;
}
rc = ksba_cert_init_from_mem (kc, cert, ncert);
@@ -373,7 +373,7 @@ cmd_readkey (ASSUAN_CONTEXT ctx, char *line)
p = ksba_cert_get_public_key (kc);
if (!p)
{
- rc = GNUPG_No_Public_Key;
+ rc = gpg_error (GPG_ERR_NO_PUBKEY);
goto leave;
}
@@ -439,7 +439,7 @@ pin_cb (void *opaque, const char *info, char **retstr)
rc = asprintf (&command, "NEEDPIN %s", info);
if (rc < 0)
- return GNUPG_Out_Of_Core;
+ return out_of_core ();
/* FIXME: Write an inquire function which returns the result in
secure memory */
@@ -452,7 +452,7 @@ pin_cb (void *opaque, const char *info, char **retstr)
{
/* We require that the returned value is an UTF-8 string */
xfree (value);
- return GNUPG_Invalid_Response;
+ return gpg_error (GPG_ERR_INVALID_RESPONSE);
}
*retstr = value;
return 0;
diff --git a/scd/scdaemon.c b/scd/scdaemon.c
index 902324ad7..5ab50a5b4 100644
--- a/scd/scdaemon.c
+++ b/scd/scdaemon.c
@@ -69,7 +69,6 @@ enum cmd_and_opt_values
oDaemon,
oBatch,
oReaderPort,
- oPrintATR,
aTest };
@@ -93,7 +92,6 @@ static ARGPARSE_OPTS opts[] = {
{ oNoDetach, "no-detach" ,0, N_("do not detach from the console")},
{ oLogFile, "log-file" ,2, N_("use a log file for the server")},
{ oReaderPort, "reader-port", 1, N_("|N|connect to reader at port N")},
- { oPrintATR, "print-atr", 0, N_("print ATR and exit")},
{0}
};
@@ -233,9 +231,6 @@ main (int argc, char **argv )
char *logfile = NULL;
int debug_wait = 0;
int reader_port = 32768; /* First USB reader. */
- int print_atr = 0;
-
-
set_strusage (my_strusage);
gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
@@ -371,7 +366,6 @@ main (int argc, char **argv )
case oDaemon: is_daemon = 1; break;
case oReaderPort: reader_port = pargs.r.ret_int; break;
- case oPrintATR: print_atr = 1; break;
default : pargs.err = configfp? 1:2; break;
}
@@ -410,12 +404,6 @@ main (int argc, char **argv )
}
- if (print_atr)
- {
- apdu_open_reader (reader_port);
- scd_exit (0);
- }
-
if (debug_wait && pipe_server)
{
log_debug ("waiting for debugger - my pid is %u .....\n",
diff --git a/scd/scdaemon.h b/scd/scdaemon.h
index 9fbf891bb..59d40e519 100644
--- a/scd/scdaemon.h
+++ b/scd/scdaemon.h
@@ -1,5 +1,5 @@
/* scdaemon.h - Global definitions for the SCdaemon
- * Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -21,11 +21,27 @@
#ifndef SCDAEMON_H
#define SCDAEMON_H
+#ifdef GPG_ERR_SOURCE_DEFAULT
+#error GPG_ERR_SOURCE_DEFAULT already defined
+#endif
+#define GPG_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_SCD
+#include <gpg-error.h>
+#include <errno.h>
+
#include <time.h>
#include <gcrypt.h>
#include "../common/util.h"
#include "../common/errors.h"
+/* Convenience funcion to be used instead of returning the old
+ GNUPG_Out_Of_Core. */
+static __inline__ gpg_error_t
+out_of_core (void)
+{
+ return gpg_error (gpg_err_code_from_errno (errno));
+}
+
+
#define MAX_DIGEST_LEN 24
/* A large struct name "opt" to keep global flags */
@@ -48,6 +64,7 @@ struct {
#define DBG_MEMSTAT_VALUE 128 /* show memory statistics */
#define DBG_HASHING_VALUE 512 /* debug hashing operations */
#define DBG_ASSUAN_VALUE 1024
+#define DBG_CARD_IO_VALUE 2048
#define DBG_COMMAND (opt.debug & DBG_COMMAND_VALUE)
#define DBG_CRYPTO (opt.debug & DBG_CRYPTO_VALUE)
@@ -55,6 +72,7 @@ struct {
#define DBG_CACHE (opt.debug & DBG_CACHE_VALUE)
#define DBG_HASHING (opt.debug & DBG_HASHING_VALUE)
#define DBG_ASSUAN (opt.debug & DBG_ASSUAN_VALUE)
+#define DBG_CARD_IO (opt.debug & DBG_CARD_IO_VALUE)
struct server_local_s;
struct card_ctx_s;