* app-openpgp.c (do_setattr): Add setting of the URL.
[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
32 /* The select the best fitting application and return a context.
33    Returns NULL if no application was found or no card is present. */
34 APP
35 select_application (void)
36 {
37   int reader_port = 32768; /* First USB reader. */
38   int slot;
39   int rc;
40   APP app;
41
42   slot = apdu_open_reader (reader_port);
43   if (slot == -1)
44     {
45       log_error ("card reader not available\n");
46       return NULL;
47     }
48
49   app = xtrycalloc (1, sizeof *app);
50   if (!app)
51     {
52       rc = out_of_core ();
53       log_info ("error allocating context: %s\n", gpg_strerror (rc));
54       /*apdu_close_reader (slot);*/
55       return NULL;
56     }
57
58   app->slot = slot;
59   rc = app_select_openpgp (app, &app->serialno, &app->serialnolen);
60   if (rc)
61     {
62 /*        apdu_close_reader (slot); */
63       log_info ("selecting openpgp failed: %s\n", gpg_strerror (rc));
64       xfree (app);
65       return NULL;
66     }
67
68   app->initialized = 1;
69   return app;
70 }
71
72
73
74 /* Retrieve the serial number and the time of the last update of the
75    card.  The serial number is returned as a malloced string (hex
76    encoded) in SERIAL and the time of update is returned in STAMP.  If
77    no update time is available the returned value is 0.  Caller must
78    free SERIAL unless the function returns an error. */
79 int 
80 app_get_serial_and_stamp (APP app, char **serial, time_t *stamp)
81 {
82   unsigned char *buf, *p;
83   int i;
84
85   if (!app || !serial || !stamp)
86     return gpg_error (GPG_ERR_INV_VALUE);
87
88   *serial = NULL;
89   *stamp = 0; /* not available */
90
91   buf = xtrymalloc (app->serialnolen * 2 + 1);
92   if (!buf)
93     return gpg_error_from_errno (errno);
94   for (p=buf, i=0; i < app->serialnolen; p +=2, i++)
95     sprintf (p, "%02X", app->serialno[i]);
96   *p = 0;
97   *serial = buf;
98   return 0;
99 }
100
101
102 /* Write out the application specifig status lines for the LEARN
103    command. */
104 int
105 app_write_learn_status (APP app, CTRL ctrl)
106 {
107   if (!app)
108     return gpg_error (GPG_ERR_INV_VALUE);
109   if (!app->initialized)
110     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
111   if (!app->fnc.learn_status)
112     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
113   return app->fnc.learn_status (app, ctrl);
114 }
115
116
117 /* Perform a SETATTR operation.  */
118 int 
119 app_setattr (APP app, const char *name,
120              int (*pincb)(void*, const char *, char **),
121              void *pincb_arg,
122              const unsigned char *value, size_t valuelen)
123 {
124   if (!app || !name || !*name || !value)
125     return gpg_error (GPG_ERR_INV_VALUE);
126   if (!app->initialized)
127     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
128   if (!app->fnc.setattr)
129     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
130   return app->fnc.setattr (app, name, pincb, pincb_arg, value, valuelen);
131 }
132
133 /* Create the signature and return the allocated result in OUTDATA.
134    If a PIN is required the PINCB will be used to ask for the PIN; it
135    should return the PIN in an allocated buffer and put it into PIN.  */
136 int 
137 app_sign (APP app, const char *keyidstr, int hashalgo,
138           int (pincb)(void*, const char *, char **),
139           void *pincb_arg,
140           const void *indata, size_t indatalen,
141           unsigned char **outdata, size_t *outdatalen )
142 {
143   int rc;
144
145   if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
146     return gpg_error (GPG_ERR_INV_VALUE);
147   if (!app->initialized)
148     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
149   if (!app->fnc.sign)
150     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
151   rc = app->fnc.sign (app, keyidstr, hashalgo,
152                       pincb, pincb_arg,
153                       indata, indatalen,
154                       outdata, outdatalen);
155   if (opt.verbose)
156     log_info ("operation sign result: %s\n", gpg_strerror (rc));
157   return rc;
158 }
159
160
161 /* Decrypt the data in INDATA and return the allocated result in OUTDATA.
162    If a PIN is required the PINCB will be used to ask for the PIN; it
163    should return the PIN in an allocated buffer and put it into PIN.  */
164 int 
165 app_decipher (APP app, const char *keyidstr,
166               int (pincb)(void*, const char *, char **),
167               void *pincb_arg,
168               const void *indata, size_t indatalen,
169               unsigned char **outdata, size_t *outdatalen )
170 {
171   int rc;
172
173   if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
174     return gpg_error (GPG_ERR_INV_VALUE);
175   if (!app->initialized)
176     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
177   if (!app->fnc.decipher)
178     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
179   rc = app->fnc.decipher (app, keyidstr,
180                           pincb, pincb_arg,
181                           indata, indatalen,
182                           outdata, outdatalen);
183   if (opt.verbose)
184     log_info ("operation decipher result: %s\n", gpg_strerror (rc));
185   return rc;
186 }
187
188
189 /* Perform a SETATTR operation.  */
190 int 
191 app_genkey (APP app, CTRL ctrl, const char *keynostr, unsigned int flags,
192             int (*pincb)(void*, const char *, char **),
193             void *pincb_arg)
194 {
195   int rc;
196
197   if (!app || !keynostr || !*keynostr || !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.genkey)
202     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
203   rc = app->fnc.genkey (app, ctrl, keynostr, flags, pincb, pincb_arg);
204   if (opt.verbose)
205     log_info ("operation genkey result: %s\n", gpg_strerror (rc));
206   return rc;
207 }
208