d395fe559df69cd634458dfb599e42c7205f5d65
[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 "tlv.h"
33
34
35 /* If called with NAME as NULL, select the best fitting application
36    and return a context; otherwise select the application with NAME
37    and return a context.  SLOT identifies the reader device. Returns
38    NULL if no application was found or no card is present. */
39 APP
40 select_application (ctrl_t ctrl, int slot, const char *name)
41 {
42   int rc;
43   APP app;
44   unsigned char *result = NULL;
45   size_t resultlen;
46
47   app = xtrycalloc (1, sizeof *app);
48   if (!app)
49     {
50       rc = gpg_error (gpg_err_code_from_errno (errno));
51       log_info ("error allocating context: %s\n", gpg_strerror (rc));
52       return NULL;
53     }
54   app->slot = slot;
55
56   /* Fixme: We should now first check whether a card is at all
57      present. */
58
59   /* Try to read the GDO file first to get a default serial number. */
60   rc = iso7816_select_file (slot, 0x3F00, 1, NULL, NULL);
61   if (!rc)
62     rc = iso7816_select_file (slot, 0x2F02, 0, NULL, NULL);
63   if (!rc)
64     rc = iso7816_read_binary (slot, 0, 0, &result, &resultlen);
65   if (!rc)
66     {
67       size_t n;
68       const unsigned char *p;
69
70       p = find_tlv (result, resultlen, 0x5A, &n);
71       if (p && n && n >= (resultlen - (p - result)))
72         {
73           /* The GDO file is pretty short, thus we simply reuse it for
74              storing the serial number. */
75           memmove (result, p, n);
76           app->serialno = result;
77           app->serialnolen = n;
78         }
79       else
80         xfree (result);
81       result = NULL;
82     }
83
84
85   rc = gpg_error (GPG_ERR_NOT_FOUND);
86
87   if (!name || !strcmp (name, "openpgp"))
88     rc = app_select_openpgp (app);
89   if (rc && (!name || !strcmp (name, "nks")))
90     rc = app_select_nks (app);
91   if (rc && (!name || !strcmp (name, "dinsig")))
92     rc = app_select_dinsig (app);
93   if (rc && name)
94     rc = gpg_error (GPG_ERR_NOT_SUPPORTED);
95
96   if (rc)
97     {
98       if (name)
99         log_info ("can't select application `%s': %s\n",
100                   name, gpg_strerror (rc));
101       else
102         log_info ("no supported card application found: %s\n",
103                   gpg_strerror (rc));
104       xfree (app);
105       return NULL;
106     }
107
108   app->initialized = 1;
109   return app;
110 }
111
112
113 void
114 release_application (app_t app)
115 {
116   if (!app)
117     return;
118
119   xfree (app->serialno);
120   xfree (app);
121 }
122
123
124
125 /* Retrieve the serial number and the time of the last update of the
126    card.  The serial number is returned as a malloced string (hex
127    encoded) in SERIAL and the time of update is returned in STAMP.  If
128    no update time is available the returned value is 0.  Caller must
129    free SERIAL unless the function returns an error.  If STAMP is not
130    of interest, NULL may be passed. */
131 int 
132 app_get_serial_and_stamp (app_t app, char **serial, time_t *stamp)
133 {
134   unsigned char *buf, *p;
135   int i;
136
137   if (!app || !serial)
138     return gpg_error (GPG_ERR_INV_VALUE);
139
140   *serial = NULL;
141   if (stamp)
142     *stamp = 0; /* not available */
143
144   buf = xtrymalloc (app->serialnolen * 2 + 1);
145   if (!buf)
146     return gpg_error_from_errno (errno);
147   for (p=buf, i=0; i < app->serialnolen; p +=2, i++)
148     sprintf (p, "%02X", app->serialno[i]);
149   *p = 0;
150   *serial = buf;
151   return 0;
152 }
153
154
155 /* Write out the application specifig status lines for the LEARN
156    command. */
157 int
158 app_write_learn_status (APP app, CTRL ctrl)
159 {
160   if (!app)
161     return gpg_error (GPG_ERR_INV_VALUE);
162   if (!app->initialized)
163     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
164   if (!app->fnc.learn_status)
165     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
166
167   if (app->apptype)
168     send_status_info (ctrl, "APPTYPE",
169                       app->apptype, strlen (app->apptype), NULL, 0);
170
171   return app->fnc.learn_status (app, ctrl);
172 }
173
174
175 /* Read the certificate with id CERTID (as returned by learn_status in
176    the CERTINFO status lines) and return it in the freshly allocated
177    buffer put into CERT and the length of the certificate put into
178    CERTLEN. */
179 int
180 app_readcert (app_t app, const char *certid,
181               unsigned char **cert, size_t *certlen)
182 {
183   if (!app)
184     return gpg_error (GPG_ERR_INV_VALUE);
185   if (!app->initialized)
186     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
187   if (!app->fnc.readcert)
188     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
189
190   return app->fnc.readcert (app, certid, cert, certlen);
191 }
192
193
194 /* Perform a GETATTR operation.  */
195 int 
196 app_getattr (APP app, CTRL ctrl, const char *name)
197 {
198   if (!app || !name || !*name)
199     return gpg_error (GPG_ERR_INV_VALUE);
200   if (!app->initialized)
201     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
202   if (!app->fnc.getattr)
203     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
204   return app->fnc.getattr (app, ctrl, name);
205 }
206
207 /* Perform a SETATTR operation.  */
208 int 
209 app_setattr (APP app, const char *name,
210              int (*pincb)(void*, const char *, char **),
211              void *pincb_arg,
212              const unsigned char *value, size_t valuelen)
213 {
214   if (!app || !name || !*name || !value)
215     return gpg_error (GPG_ERR_INV_VALUE);
216   if (!app->initialized)
217     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
218   if (!app->fnc.setattr)
219     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
220   return app->fnc.setattr (app, name, pincb, pincb_arg, value, valuelen);
221 }
222
223 /* Create the signature and return the allocated result in OUTDATA.
224    If a PIN is required the PINCB will be used to ask for the PIN; it
225    should return the PIN in an allocated buffer and put it into PIN.  */
226 int 
227 app_sign (APP app, const char *keyidstr, int hashalgo,
228           int (pincb)(void*, const char *, char **),
229           void *pincb_arg,
230           const void *indata, size_t indatalen,
231           unsigned char **outdata, size_t *outdatalen )
232 {
233   int rc;
234
235   if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
236     return gpg_error (GPG_ERR_INV_VALUE);
237   if (!app->initialized)
238     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
239   if (!app->fnc.sign)
240     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
241   rc = app->fnc.sign (app, keyidstr, hashalgo,
242                       pincb, pincb_arg,
243                       indata, indatalen,
244                       outdata, outdatalen);
245   if (opt.verbose)
246     log_info ("operation sign result: %s\n", gpg_strerror (rc));
247   return rc;
248 }
249
250 /* Create the signature using the INTERNAL AUTHENTICATE command and
251    return the allocated result in OUTDATA.  If a PIN is required the
252    PINCB will be used to ask for the PIN; it should return the PIN in
253    an allocated buffer and put it into PIN.  */
254 int 
255 app_auth (APP app, const char *keyidstr,
256           int (pincb)(void*, const char *, char **),
257           void *pincb_arg,
258           const void *indata, size_t indatalen,
259           unsigned char **outdata, size_t *outdatalen )
260 {
261   int rc;
262
263   if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
264     return gpg_error (GPG_ERR_INV_VALUE);
265   if (!app->initialized)
266     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
267   if (!app->fnc.auth)
268     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
269   rc = app->fnc.auth (app, keyidstr,
270                       pincb, pincb_arg,
271                       indata, indatalen,
272                       outdata, outdatalen);
273   if (opt.verbose)
274     log_info ("operation auth result: %s\n", gpg_strerror (rc));
275   return rc;
276 }
277
278
279 /* Decrypt the data in INDATA and return the allocated result in OUTDATA.
280    If a PIN is required the PINCB will be used to ask for the PIN; it
281    should return the PIN in an allocated buffer and put it into PIN.  */
282 int 
283 app_decipher (APP app, const char *keyidstr,
284               int (pincb)(void*, const char *, char **),
285               void *pincb_arg,
286               const void *indata, size_t indatalen,
287               unsigned char **outdata, size_t *outdatalen )
288 {
289   int rc;
290
291   if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
292     return gpg_error (GPG_ERR_INV_VALUE);
293   if (!app->initialized)
294     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
295   if (!app->fnc.decipher)
296     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
297   rc = app->fnc.decipher (app, keyidstr,
298                           pincb, pincb_arg,
299                           indata, indatalen,
300                           outdata, outdatalen);
301   if (opt.verbose)
302     log_info ("operation decipher result: %s\n", gpg_strerror (rc));
303   return rc;
304 }
305
306
307 /* Perform a SETATTR operation.  */
308 int 
309 app_genkey (APP app, CTRL ctrl, const char *keynostr, unsigned int flags,
310             int (*pincb)(void*, const char *, char **),
311             void *pincb_arg)
312 {
313   int rc;
314
315   if (!app || !keynostr || !*keynostr || !pincb)
316     return gpg_error (GPG_ERR_INV_VALUE);
317   if (!app->initialized)
318     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
319   if (!app->fnc.genkey)
320     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
321   rc = app->fnc.genkey (app, ctrl, keynostr, flags, pincb, pincb_arg);
322   if (opt.verbose)
323     log_info ("operation genkey result: %s\n", gpg_strerror (rc));
324   return rc;
325 }
326
327
328 /* Perform a GET CHALLENGE operation.  This fucntion is special as it
329    directly accesses the card without any application specific
330    wrapper. */
331 int
332 app_get_challenge (APP app, size_t nbytes, unsigned char *buffer)
333 {
334   if (!app || !nbytes || !buffer)
335     return gpg_error (GPG_ERR_INV_VALUE);
336   if (!app->initialized)
337     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
338   return iso7816_get_challenge (app->slot, nbytes, buffer);
339 }
340
341
342
343 /* Perform a CHANGE REFERENCE DATA or RESET RETRY COUNTER operation.  */
344 int 
345 app_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode,
346                 int (*pincb)(void*, const char *, char **),
347                 void *pincb_arg)
348 {
349   int rc;
350
351   if (!app || !chvnostr || !*chvnostr || !pincb)
352     return gpg_error (GPG_ERR_INV_VALUE);
353   if (!app->initialized)
354     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
355   if (!app->fnc.change_pin)
356     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
357   rc = app->fnc.change_pin (app, ctrl, chvnostr, reset_mode, pincb, pincb_arg);
358   if (opt.verbose)
359     log_info ("operation change_pin result: %s\n", gpg_strerror (rc));
360   return rc;
361 }
362
363
364 /* Perform a VERIFY operation without doing anything lese.  This may
365    be used to initialze a the PION cache for long lasting other
366    operations.  Its use is highly application dependent. */
367 int 
368 app_check_pin (APP app, const char *keyidstr,
369                int (*pincb)(void*, const char *, char **),
370                void *pincb_arg)
371 {
372   int rc;
373
374   if (!app || !keyidstr || !*keyidstr || !pincb)
375     return gpg_error (GPG_ERR_INV_VALUE);
376   if (!app->initialized)
377     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
378   if (!app->fnc.check_pin)
379     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
380   rc = app->fnc.check_pin (app, keyidstr, pincb, pincb_arg);
381   if (opt.verbose)
382     log_info ("operation check_pin result: %s\n", gpg_strerror (rc));
383   return rc;
384 }
385