diff --git a/scd/Makefile.am b/scd/Makefile.am index 6212e6150..80e4c0f97 100644 --- a/scd/Makefile.am +++ b/scd/Makefile.am @@ -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) - -# 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 index 640cec776..000000000 --- a/scd/card-common.h +++ /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 . - */ - -#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 index 5be006179..000000000 --- a/scd/card-dinsig.c +++ /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 . - */ - -/* 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 -#include -#include -#include -#include -#include - -#ifdef HAVE_OPENSC -#include -#include "scdaemon.h" -#include - -#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; -} - - - -/* 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 index 4af447278..000000000 --- a/scd/card-p15.c +++ /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 . - */ - -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_OPENSC -#include - -#include "scdaemon.h" -#include -#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; -} - - - -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; -} - - - - - -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 index a582c500f..000000000 --- a/scd/card.c +++ /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 . - */ - -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_OPENSC -#include -#endif - -#include "scdaemon.h" -#include - -#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; -} - - - - - - - -/* 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 index 843603a24..000000000 --- a/scd/pcsc-wrapper.c +++ /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 . - */ - -/* - 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 -#endif -#include -#include -#include -#include -#include -#include -#include -#include - - -#define PGM "pcsc-wrapper" - -/* Allow for a standalone build. */ -#ifdef VERSION -#define MYVERSION_LINE PGM " ("GNUPG_NAME") " VERSION -#define BUGREPORT_LINE "\nReport bugs to .\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 index eb246c492..000000000 --- a/scd/sc-copykeys.c +++ /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 . - */ - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "scdaemon.h" -#include - -#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 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 public exponent - 0xC1 prime p - 0xC2 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); -}