1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-03 22:56:33 +02:00

Make use of libgpg-error

This commit is contained in:
Werner Koch 2003-06-03 19:55:50 +00:00
parent 7c9855aaa2
commit c3cdaeeff7
58 changed files with 1110 additions and 684 deletions

View file

@ -1,3 +1,25 @@
2003-06-03 Werner Koch <wk@gnupg.org>
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 <wk@gnupg.org>
* atr.c, atr.h: New.
* sc-investigate.c: Dump the ATR in a human readable format.
2003-05-08 Werner Koch <wk@gnupg.org>
* 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 <wk@gnupg.org>
* scdaemon.c: New options --print-atr and --reader-port

View file

@ -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

View file

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

View file

@ -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*/

View file

@ -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 --*/

View file

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

View file

@ -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
{

View file

@ -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,

View file

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

View file

@ -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",

View file

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