aboutsummaryrefslogtreecommitdiffstats
path: root/scd/app.c
diff options
context:
space:
mode:
Diffstat (limited to 'scd/app.c')
-rw-r--r--scd/app.c391
1 files changed, 0 insertions, 391 deletions
diff --git a/scd/app.c b/scd/app.c
deleted file mode 100644
index a9a9243eb..000000000
--- a/scd/app.c
+++ /dev/null
@@ -1,391 +0,0 @@
-/* app.c - Application selection.
- * 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-
-#include "scdaemon.h"
-#include "app-common.h"
-#include "apdu.h"
-#include "iso7816.h"
-#include "tlv.h"
-
-
-/* If called with NAME as NULL, select the best fitting application
- and return a context; otherwise select the application with NAME
- and return a context. SLOT identifies the reader device. Returns
- NULL if no application was found or no card is present. */
-APP
-select_application (ctrl_t ctrl, int slot, const char *name)
-{
- int rc;
- APP app;
- unsigned char *result = NULL;
- size_t resultlen;
-
- app = xtrycalloc (1, sizeof *app);
- if (!app)
- {
- rc = gpg_error (gpg_err_code_from_errno (errno));
- log_info ("error allocating context: %s\n", gpg_strerror (rc));
- return NULL;
- }
- app->slot = slot;
-
- /* Fixme: We should now first check whether a card is at all
- present. */
-
- /* Try to read the GDO file first to get a default serial number. */
- rc = iso7816_select_file (slot, 0x3F00, 1, NULL, NULL);
- if (!rc)
- rc = iso7816_select_file (slot, 0x2F02, 0, NULL, NULL);
- if (!rc)
- rc = iso7816_read_binary (slot, 0, 0, &result, &resultlen);
- if (!rc)
- {
- size_t n;
- const unsigned char *p;
-
- p = find_tlv (result, resultlen, 0x5A, &n);
- if (p && n && n >= (resultlen - (p - result)))
- {
- /* The GDO file is pretty short, thus we simply reuse it for
- storing the serial number. */
- memmove (result, p, n);
- app->serialno = result;
- app->serialnolen = n;
- }
- else
- xfree (result);
- result = NULL;
- }
-
-
- rc = gpg_error (GPG_ERR_NOT_FOUND);
-
- if (!name || !strcmp (name, "openpgp"))
- rc = app_select_openpgp (app);
- if (rc && (!name || !strcmp (name, "nks")))
- rc = app_select_nks (app);
- if (rc && (!name || !strcmp (name, "dinsig")))
- rc = app_select_dinsig (app);
- if (rc && name)
- rc = gpg_error (GPG_ERR_NOT_SUPPORTED);
-
- if (rc)
- {
- if (name)
- log_info ("can't select application `%s': %s\n",
- name, gpg_strerror (rc));
- else
- log_info ("no supported card application found: %s\n",
- gpg_strerror (rc));
- xfree (app);
- return NULL;
- }
-
- app->initialized = 1;
- return app;
-}
-
-
-void
-release_application (app_t app)
-{
- if (!app)
- return;
-
- if (app->fnc.deinit)
- {
- app->fnc.deinit (app);
- app->fnc.deinit = NULL;
- }
-
- xfree (app->serialno);
- xfree (app);
-}
-
-
-
-/* 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. Caller must
- free SERIAL unless the function returns an error. If STAMP is not
- of interest, NULL may be passed. */
-int
-app_get_serial_and_stamp (app_t app, char **serial, time_t *stamp)
-{
- unsigned char *buf, *p;
- int i;
-
- if (!app || !serial)
- return gpg_error (GPG_ERR_INV_VALUE);
-
- *serial = NULL;
- if (stamp)
- *stamp = 0; /* not available */
-
- buf = xtrymalloc (app->serialnolen * 2 + 1);
- if (!buf)
- return gpg_error_from_errno (errno);
- for (p=buf, i=0; i < app->serialnolen; p +=2, i++)
- sprintf (p, "%02X", app->serialno[i]);
- *p = 0;
- *serial = buf;
- return 0;
-}
-
-
-/* Write out the application specifig status lines for the LEARN
- command. */
-int
-app_write_learn_status (APP app, CTRL ctrl)
-{
- if (!app)
- return gpg_error (GPG_ERR_INV_VALUE);
- if (!app->initialized)
- return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
- if (!app->fnc.learn_status)
- return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
-
- if (app->apptype)
- send_status_info (ctrl, "APPTYPE",
- app->apptype, strlen (app->apptype), NULL, 0);
-
- return app->fnc.learn_status (app, ctrl);
-}
-
-
-/* Read the certificate with id CERTID (as returned by learn_status in
- the CERTINFO status lines) and return it in the freshly allocated
- buffer put into CERT and the length of the certificate put into
- CERTLEN. */
-int
-app_readcert (app_t app, const char *certid,
- unsigned char **cert, size_t *certlen)
-{
- if (!app)
- return gpg_error (GPG_ERR_INV_VALUE);
- if (!app->initialized)
- return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
- if (!app->fnc.readcert)
- return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
-
- return app->fnc.readcert (app, certid, cert, certlen);
-}
-
-
-/* Perform a GETATTR operation. */
-int
-app_getattr (APP app, CTRL ctrl, const char *name)
-{
- if (!app || !name || !*name)
- return gpg_error (GPG_ERR_INV_VALUE);
- if (!app->initialized)
- return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
- if (!app->fnc.getattr)
- return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
- return app->fnc.getattr (app, ctrl, name);
-}
-
-/* Perform a SETATTR operation. */
-int
-app_setattr (APP app, const char *name,
- int (*pincb)(void*, const char *, char **),
- void *pincb_arg,
- const unsigned char *value, size_t valuelen)
-{
- if (!app || !name || !*name || !value)
- return gpg_error (GPG_ERR_INV_VALUE);
- if (!app->initialized)
- return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
- if (!app->fnc.setattr)
- return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
- return app->fnc.setattr (app, name, pincb, pincb_arg, value, valuelen);
-}
-
-/* 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
-app_sign (APP app, 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 (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
- return gpg_error (GPG_ERR_INV_VALUE);
- if (!app->initialized)
- return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
- if (!app->fnc.sign)
- return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
- rc = app->fnc.sign (app, keyidstr, hashalgo,
- pincb, pincb_arg,
- indata, indatalen,
- outdata, outdatalen);
- if (opt.verbose)
- log_info ("operation sign result: %s\n", gpg_strerror (rc));
- return rc;
-}
-
-/* Create the signature using the INTERNAL AUTHENTICATE command 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
-app_auth (APP app, 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 (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
- return gpg_error (GPG_ERR_INV_VALUE);
- if (!app->initialized)
- return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
- if (!app->fnc.auth)
- return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
- rc = app->fnc.auth (app, keyidstr,
- pincb, pincb_arg,
- indata, indatalen,
- outdata, outdatalen);
- if (opt.verbose)
- log_info ("operation auth result: %s\n", gpg_strerror (rc));
- return rc;
-}
-
-
-/* Decrypt the data in INDATA and return the allocated result in OUTDATA.
- If a PIN is required the PINCB will be used to ask for the PIN; it
- should return the PIN in an allocated buffer and put it into PIN. */
-int
-app_decipher (APP app, 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 (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
- return gpg_error (GPG_ERR_INV_VALUE);
- if (!app->initialized)
- return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
- if (!app->fnc.decipher)
- return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
- rc = app->fnc.decipher (app, keyidstr,
- pincb, pincb_arg,
- indata, indatalen,
- outdata, outdatalen);
- if (opt.verbose)
- log_info ("operation decipher result: %s\n", gpg_strerror (rc));
- return rc;
-}
-
-
-/* Perform a SETATTR operation. */
-int
-app_genkey (APP app, CTRL ctrl, const char *keynostr, unsigned int flags,
- int (*pincb)(void*, const char *, char **),
- void *pincb_arg)
-{
- int rc;
-
- if (!app || !keynostr || !*keynostr || !pincb)
- return gpg_error (GPG_ERR_INV_VALUE);
- if (!app->initialized)
- return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
- if (!app->fnc.genkey)
- return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
- rc = app->fnc.genkey (app, ctrl, keynostr, flags, pincb, pincb_arg);
- if (opt.verbose)
- log_info ("operation genkey result: %s\n", gpg_strerror (rc));
- return rc;
-}
-
-
-/* Perform a GET CHALLENGE operation. This fucntion is special as it
- directly accesses the card without any application specific
- wrapper. */
-int
-app_get_challenge (APP app, size_t nbytes, unsigned char *buffer)
-{
- if (!app || !nbytes || !buffer)
- return gpg_error (GPG_ERR_INV_VALUE);
- if (!app->initialized)
- return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
- return iso7816_get_challenge (app->slot, nbytes, buffer);
-}
-
-
-
-/* Perform a CHANGE REFERENCE DATA or RESET RETRY COUNTER operation. */
-int
-app_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode,
- int (*pincb)(void*, const char *, char **),
- void *pincb_arg)
-{
- int rc;
-
- if (!app || !chvnostr || !*chvnostr || !pincb)
- return gpg_error (GPG_ERR_INV_VALUE);
- if (!app->initialized)
- return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
- if (!app->fnc.change_pin)
- return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
- rc = app->fnc.change_pin (app, ctrl, chvnostr, reset_mode, pincb, pincb_arg);
- if (opt.verbose)
- log_info ("operation change_pin result: %s\n", gpg_strerror (rc));
- return rc;
-}
-
-
-/* Perform a VERIFY operation without doing anything lese. This may
- be used to initialze a the PION cache for long lasting other
- operations. Its use is highly application dependent. */
-int
-app_check_pin (APP app, const char *keyidstr,
- int (*pincb)(void*, const char *, char **),
- void *pincb_arg)
-{
- int rc;
-
- if (!app || !keyidstr || !*keyidstr || !pincb)
- return gpg_error (GPG_ERR_INV_VALUE);
- if (!app->initialized)
- return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
- if (!app->fnc.check_pin)
- return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
- rc = app->fnc.check_pin (app, keyidstr, pincb, pincb_arg);
- if (opt.verbose)
- log_info ("operation check_pin result: %s\n", gpg_strerror (rc));
- return rc;
-}
-