* command.c (cmd_checkpin): New.
[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
27
28 #include "scdaemon.h"
29 #include "app-common.h"
30 #include "apdu.h"
31 #include "iso7816.h"
32 #include "dynload.h"
33
34 static char *default_reader_port;
35
36 void
37 app_set_default_reader_port (const char *portstr)
38 {
39   xfree (default_reader_port);
40   default_reader_port = portstr? xstrdup (portstr): NULL;
41 }
42
43
44 /* The select the best fitting application and return a context.
45    Returns NULL if no application was found or no card is present. */
46 APP
47 select_application (void)
48 {
49   int slot;
50   int rc;
51   APP app;
52
53   slot = apdu_open_reader (default_reader_port);
54   if (slot == -1)
55     {
56       log_error ("card reader not available\n");
57       return NULL;
58     }
59
60   app = xtrycalloc (1, sizeof *app);
61   if (!app)
62     {
63       rc = out_of_core ();
64       log_info ("error allocating context: %s\n", gpg_strerror (rc));
65       /*apdu_close_reader (slot);*/
66       return NULL;
67     }
68
69   app->slot = slot;
70   rc = app_select_openpgp (app, &app->serialno, &app->serialnolen);
71   if (rc)
72     {
73 /*        apdu_close_reader (slot); */
74       log_info ("selecting openpgp failed: %s\n", gpg_strerror (rc));
75       xfree (app);
76       return NULL;
77     }
78
79   app->initialized = 1;
80   return app;
81 }
82
83
84
85 /* Retrieve the serial number and the time of the last update of the
86    card.  The serial number is returned as a malloced string (hex
87    encoded) in SERIAL and the time of update is returned in STAMP.  If
88    no update time is available the returned value is 0.  Caller must
89    free SERIAL unless the function returns an error. */
90 int 
91 app_get_serial_and_stamp (APP app, char **serial, time_t *stamp)
92 {
93   unsigned char *buf, *p;
94   int i;
95
96   if (!app || !serial || !stamp)
97     return gpg_error (GPG_ERR_INV_VALUE);
98
99   *serial = NULL;
100   *stamp = 0; /* not available */
101
102   buf = xtrymalloc (app->serialnolen * 2 + 1);
103   if (!buf)
104     return gpg_error_from_errno (errno);
105   for (p=buf, i=0; i < app->serialnolen; p +=2, i++)
106     sprintf (p, "%02X", app->serialno[i]);
107   *p = 0;
108   *serial = buf;
109   return 0;
110 }
111
112
113 /* Write out the application specifig status lines for the LEARN
114    command. */
115 int
116 app_write_learn_status (APP app, CTRL ctrl)
117 {
118   if (!app)
119     return gpg_error (GPG_ERR_INV_VALUE);
120   if (!app->initialized)
121     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
122   if (!app->fnc.learn_status)
123     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
124   return app->fnc.learn_status (app, ctrl);
125 }
126
127
128 /* Perform a GETATTR operation.  */
129 int 
130 app_getattr (APP app, CTRL ctrl, const char *name)
131 {
132   if (!app || !name || !*name)
133     return gpg_error (GPG_ERR_INV_VALUE);
134   if (!app->initialized)
135     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
136   if (!app->fnc.getattr)
137     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
138   return app->fnc.getattr (app, ctrl, name);
139 }
140
141 /* Perform a SETATTR operation.  */
142 int 
143 app_setattr (APP app, const char *name,
144              int (*pincb)(void*, const char *, char **),
145              void *pincb_arg,
146              const unsigned char *value, size_t valuelen)
147 {
148   if (!app || !name || !*name || !value)
149     return gpg_error (GPG_ERR_INV_VALUE);
150   if (!app->initialized)
151     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
152   if (!app->fnc.setattr)
153     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
154   return app->fnc.setattr (app, name, pincb, pincb_arg, value, valuelen);
155 }
156
157 /* Create the signature and return the allocated result in OUTDATA.
158    If a PIN is required the PINCB will be used to ask for the PIN; it
159    should return the PIN in an allocated buffer and put it into PIN.  */
160 int 
161 app_sign (APP app, const char *keyidstr, int hashalgo,
162           int (pincb)(void*, const char *, char **),
163           void *pincb_arg,
164           const void *indata, size_t indatalen,
165           unsigned char **outdata, size_t *outdatalen )
166 {
167   int rc;
168
169   if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
170     return gpg_error (GPG_ERR_INV_VALUE);
171   if (!app->initialized)
172     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
173   if (!app->fnc.sign)
174     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
175   rc = app->fnc.sign (app, keyidstr, hashalgo,
176                       pincb, pincb_arg,
177                       indata, indatalen,
178                       outdata, outdatalen);
179   if (opt.verbose)
180     log_info ("operation sign result: %s\n", gpg_strerror (rc));
181   return rc;
182 }
183
184 /* Create the signature using the INTERNAL AUTHENTICATE command and
185    return the allocated result in OUTDATA.  If a PIN is required the
186    PINCB will be used to ask for the PIN; it should return the PIN in
187    an allocated buffer and put it into PIN.  */
188 int 
189 app_auth (APP app, const char *keyidstr,
190           int (pincb)(void*, const char *, char **),
191           void *pincb_arg,
192           const void *indata, size_t indatalen,
193           unsigned char **outdata, size_t *outdatalen )
194 {
195   int rc;
196
197   if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
198     return gpg_error (GPG_ERR_INV_VALUE);
199   if (!app->initialized)
200     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
201   if (!app->fnc.auth)
202     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
203   rc = app->fnc.auth (app, keyidstr,
204                       pincb, pincb_arg,
205                       indata, indatalen,
206                       outdata, outdatalen);
207   if (opt.verbose)
208     log_info ("operation auth result: %s\n", gpg_strerror (rc));
209   return rc;
210 }
211
212
213 /* Decrypt the data in INDATA and return the allocated result in OUTDATA.
214    If a PIN is required the PINCB will be used to ask for the PIN; it
215    should return the PIN in an allocated buffer and put it into PIN.  */
216 int 
217 app_decipher (APP app, const char *keyidstr,
218               int (pincb)(void*, const char *, char **),
219               void *pincb_arg,
220               const void *indata, size_t indatalen,
221               unsigned char **outdata, size_t *outdatalen )
222 {
223   int rc;
224
225   if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
226     return gpg_error (GPG_ERR_INV_VALUE);
227   if (!app->initialized)
228     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
229   if (!app->fnc.decipher)
230     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
231   rc = app->fnc.decipher (app, keyidstr,
232                           pincb, pincb_arg,
233                           indata, indatalen,
234                           outdata, outdatalen);
235   if (opt.verbose)
236     log_info ("operation decipher result: %s\n", gpg_strerror (rc));
237   return rc;
238 }
239
240
241 /* Perform a SETATTR operation.  */
242 int 
243 app_genkey (APP app, CTRL ctrl, const char *keynostr, unsigned int flags,
244             int (*pincb)(void*, const char *, char **),
245             void *pincb_arg)
246 {
247   int rc;
248
249   if (!app || !keynostr || !*keynostr || !pincb)
250     return gpg_error (GPG_ERR_INV_VALUE);
251   if (!app->initialized)
252     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
253   if (!app->fnc.genkey)
254     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
255   rc = app->fnc.genkey (app, ctrl, keynostr, flags, pincb, pincb_arg);
256   if (opt.verbose)
257     log_info ("operation genkey result: %s\n", gpg_strerror (rc));
258   return rc;
259 }
260
261
262 /* Perform a GET CHALLENGE operation.  This fucntion is special as it
263    directly accesses the card without any application specific
264    wrapper. */
265 int
266 app_get_challenge (APP app, size_t nbytes, unsigned char *buffer)
267 {
268   if (!app || !nbytes || !buffer)
269     return gpg_error (GPG_ERR_INV_VALUE);
270   if (!app->initialized)
271     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
272   return iso7816_get_challenge (app->slot, nbytes, buffer);
273 }
274
275
276
277 /* Perform a CHANGE REFERENCE DATA or RESET RETRY COUNTER operation.  */
278 int 
279 app_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode,
280                 int (*pincb)(void*, const char *, char **),
281                 void *pincb_arg)
282 {
283   int rc;
284
285   if (!app || !chvnostr || !*chvnostr || !pincb)
286     return gpg_error (GPG_ERR_INV_VALUE);
287   if (!app->initialized)
288     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
289   if (!app->fnc.change_pin)
290     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
291   rc = app->fnc.change_pin (app, ctrl, chvnostr, reset_mode, pincb, pincb_arg);
292   if (opt.verbose)
293     log_info ("operation change_pin result: %s\n", gpg_strerror (rc));
294   return rc;
295 }
296
297
298 /* Perform a VERIFY operation without doing anything lese.  This may
299    be used to initialze a the PION cache for long lasting other
300    operations.  Its use is highly application dependent. */
301 int 
302 app_check_pin (APP app, const char *keyidstr,
303                int (*pincb)(void*, const char *, char **),
304                void *pincb_arg)
305 {
306   int rc;
307
308   if (!app || !keyidstr || !*keyidstr || !pincb)
309     return gpg_error (GPG_ERR_INV_VALUE);
310   if (!app->initialized)
311     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
312   if (!app->fnc.check_pin)
313     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
314   rc = app->fnc.check_pin (app, keyidstr, pincb, pincb_arg);
315   if (opt.verbose)
316     log_info ("operation check_pin result: %s\n", gpg_strerror (rc));
317   return rc;
318 }
319
320
321
322
323
324