* options.h, import.c (parse_import_options, delete_inv_parts):
[gnupg.git] / scd / app.c
1 /* app.c - Application selection.
2  *      Copyright (C) 2003 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <errno.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <dlfcn.h>
27
28 #include "scdaemon.h"
29 #include "app-common.h"
30 #include "apdu.h"
31 #include "iso7816.h"
32
33 /* The select the best fitting application and return a context.
34    Returns NULL if no application was found or no card is present. */
35 APP
36 select_application (void)
37 {
38   int reader_port = 32768; /* First USB reader. */
39   int slot;
40   int rc;
41   APP app;
42
43   slot = apdu_open_reader (reader_port);
44   if (slot == -1)
45     {
46       log_error ("card reader not available\n");
47       return NULL;
48     }
49
50   app = xtrycalloc (1, sizeof *app);
51   if (!app)
52     {
53       rc = out_of_core ();
54       log_info ("error allocating context: %s\n", gpg_strerror (rc));
55       /*apdu_close_reader (slot);*/
56       return NULL;
57     }
58
59   app->slot = slot;
60   rc = app_select_openpgp (app, &app->serialno, &app->serialnolen);
61   if (rc)
62     {
63 /*        apdu_close_reader (slot); */
64       log_info ("selecting openpgp failed: %s\n", gpg_strerror (rc));
65       xfree (app);
66       return NULL;
67     }
68
69   app->initialized = 1;
70   return app;
71 }
72
73
74
75 /* Retrieve the serial number and the time of the last update of the
76    card.  The serial number is returned as a malloced string (hex
77    encoded) in SERIAL and the time of update is returned in STAMP.  If
78    no update time is available the returned value is 0.  Caller must
79    free SERIAL unless the function returns an error. */
80 int 
81 app_get_serial_and_stamp (APP app, char **serial, time_t *stamp)
82 {
83   unsigned char *buf, *p;
84   int i;
85
86   if (!app || !serial || !stamp)
87     return gpg_error (GPG_ERR_INV_VALUE);
88
89   *serial = NULL;
90   *stamp = 0; /* not available */
91
92   buf = xtrymalloc (app->serialnolen * 2 + 1);
93   if (!buf)
94     return gpg_error_from_errno (errno);
95   for (p=buf, i=0; i < app->serialnolen; p +=2, i++)
96     sprintf (p, "%02X", app->serialno[i]);
97   *p = 0;
98   *serial = buf;
99   return 0;
100 }
101
102
103 /* Write out the application specifig status lines for the LEARN
104    command. */
105 int
106 app_write_learn_status (APP app, CTRL ctrl)
107 {
108   if (!app)
109     return gpg_error (GPG_ERR_INV_VALUE);
110   if (!app->initialized)
111     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
112   if (!app->fnc.learn_status)
113     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
114   return app->fnc.learn_status (app, ctrl);
115 }
116
117
118 /* Perform a SETATTR operation.  */
119 int 
120 app_setattr (APP app, const char *name,
121              int (*pincb)(void*, const char *, char **),
122              void *pincb_arg,
123              const unsigned char *value, size_t valuelen)
124 {
125   if (!app || !name || !*name || !value)
126     return gpg_error (GPG_ERR_INV_VALUE);
127   if (!app->initialized)
128     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
129   if (!app->fnc.setattr)
130     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
131   return app->fnc.setattr (app, name, pincb, pincb_arg, value, valuelen);
132 }
133
134 /* Create the signature and return the allocated result in OUTDATA.
135    If a PIN is required the PINCB will be used to ask for the PIN; it
136    should return the PIN in an allocated buffer and put it into PIN.  */
137 int 
138 app_sign (APP app, const char *keyidstr, int hashalgo,
139           int (pincb)(void*, const char *, char **),
140           void *pincb_arg,
141           const void *indata, size_t indatalen,
142           unsigned char **outdata, size_t *outdatalen )
143 {
144   int rc;
145
146   if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
147     return gpg_error (GPG_ERR_INV_VALUE);
148   if (!app->initialized)
149     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
150   if (!app->fnc.sign)
151     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
152   rc = app->fnc.sign (app, keyidstr, hashalgo,
153                       pincb, pincb_arg,
154                       indata, indatalen,
155                       outdata, outdatalen);
156   if (opt.verbose)
157     log_info ("operation sign result: %s\n", gpg_strerror (rc));
158   return rc;
159 }
160
161 /* Create the signature using the INTERNAL AUTHENTICATE command and
162    return the allocated result in OUTDATA.  If a PIN is required the
163    PINCB will be used to ask for the PIN; it should return the PIN in
164    an allocated buffer and put it into PIN.  */
165 int 
166 app_auth (APP app, const char *keyidstr,
167           int (pincb)(void*, const char *, char **),
168           void *pincb_arg,
169           const void *indata, size_t indatalen,
170           unsigned char **outdata, size_t *outdatalen )
171 {
172   int rc;
173
174   if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
175     return gpg_error (GPG_ERR_INV_VALUE);
176   if (!app->initialized)
177     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
178   if (!app->fnc.auth)
179     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
180   rc = app->fnc.auth (app, keyidstr,
181                       pincb, pincb_arg,
182                       indata, indatalen,
183                       outdata, outdatalen);
184   if (opt.verbose)
185     log_info ("operation auth result: %s\n", gpg_strerror (rc));
186   return rc;
187 }
188
189
190 /* Decrypt the data in INDATA and return the allocated result in OUTDATA.
191    If a PIN is required the PINCB will be used to ask for the PIN; it
192    should return the PIN in an allocated buffer and put it into PIN.  */
193 int 
194 app_decipher (APP app, const char *keyidstr,
195               int (pincb)(void*, const char *, char **),
196               void *pincb_arg,
197               const void *indata, size_t indatalen,
198               unsigned char **outdata, size_t *outdatalen )
199 {
200   int rc;
201
202   if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
203     return gpg_error (GPG_ERR_INV_VALUE);
204   if (!app->initialized)
205     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
206   if (!app->fnc.decipher)
207     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
208   rc = app->fnc.decipher (app, keyidstr,
209                           pincb, pincb_arg,
210                           indata, indatalen,
211                           outdata, outdatalen);
212   if (opt.verbose)
213     log_info ("operation decipher result: %s\n", gpg_strerror (rc));
214   return rc;
215 }
216
217
218 /* Perform a SETATTR operation.  */
219 int 
220 app_genkey (APP app, CTRL ctrl, const char *keynostr, unsigned int flags,
221             int (*pincb)(void*, const char *, char **),
222             void *pincb_arg)
223 {
224   int rc;
225
226   if (!app || !keynostr || !*keynostr || !pincb)
227     return gpg_error (GPG_ERR_INV_VALUE);
228   if (!app->initialized)
229     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
230   if (!app->fnc.genkey)
231     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
232   rc = app->fnc.genkey (app, ctrl, keynostr, flags, pincb, pincb_arg);
233   if (opt.verbose)
234     log_info ("operation genkey result: %s\n", gpg_strerror (rc));
235   return rc;
236 }
237
238
239 /* Perform a GET CHALLENGE operation.  This fucntion is special as it
240    directly accesses the card without any application specific
241    wrapper. */
242 int
243 app_get_challenge (APP app, size_t nbytes, unsigned char *buffer)
244 {
245   if (!app || !nbytes || !buffer)
246     return gpg_error (GPG_ERR_INV_VALUE);
247   if (!app->initialized)
248     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
249   return iso7816_get_challenge (app->slot, nbytes, buffer);
250 }
251
252
253
254 /* Perform a CHANGE REFERENCE DATA or RESET RETRY COUNTER operation.  */
255 int 
256 app_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode,
257                 int (*pincb)(void*, const char *, char **),
258                 void *pincb_arg)
259 {
260   int rc;
261
262   if (!app || !chvnostr || !*chvnostr || !pincb)
263     return gpg_error (GPG_ERR_INV_VALUE);
264   if (!app->initialized)
265     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
266   if (!app->fnc.change_pin)
267     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
268   rc = app->fnc.change_pin (app, ctrl, chvnostr, reset_mode, pincb, pincb_arg);
269   if (opt.verbose)
270     log_info ("operation change_pin result: %s\n", gpg_strerror (rc));
271   return rc;
272 }
273
274
275
276
277
278