* cardglue.c (learn_status_cb): Release values before assignment
[gnupg.git] / g10 / cardglue.c
1 /* cardglue.c - mainly dispatcher for card related functions.
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 #ifndef ENABLE_CARD_SUPPORT
23 #error  no configured for card support.
24 #endif
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <errno.h>
29 #include <stdarg.h>
30 #include <assert.h>
31
32 #include "options.h"
33 #include "packet.h"
34 #include "errors.h"
35 #include "memory.h"
36 #include "util.h"
37 #include "main.h"
38 #include "status.h"
39 #include "i18n.h"
40
41 #include "cardglue.h"
42 #include "apdu.h"
43 #include "app-common.h"
44
45 struct ctrl_ctx_s {
46   int (*status_cb)(void *opaque, const char *line);
47   void *status_cb_arg;
48 };
49
50
51 static char *default_reader_port;
52 static APP current_app;
53
54
55
56
57 /* Create a serialno/fpr string from the serial number and the secret
58    key.  caller must free the returned string.  There is no error
59    return. [Taken from 1.9's keyid.c]*/
60 char *
61 serialno_and_fpr_from_sk (const unsigned char *sn, size_t snlen,
62                           PKT_secret_key *sk)
63 {
64   unsigned char fpr[MAX_FINGERPRINT_LEN];
65   size_t fprlen;
66   char *buffer, *p;
67   int i;
68   
69   fingerprint_from_sk (sk, fpr, &fprlen);
70   buffer = p = xmalloc (snlen*2 + 1 + fprlen*2 + 1);
71   for (i=0; i < snlen; i++, p+=2)
72     sprintf (p, "%02X", sn[i]);
73   *p++ = '/';
74   for (i=0; i < fprlen; i++, p+=2)
75     sprintf (p, "%02X", fpr[i]);
76   *p = 0;
77   return buffer;
78 }
79
80
81 /* Send a line with status information via assuan and escape all given
82    buffers. The variable elements are pairs of (char *, size_t),
83    terminated with a (NULL, 0). */
84 void
85 send_status_info (CTRL ctrl, const char *keyword, ...)
86 {
87   va_list arg_ptr;
88   const unsigned char *value;
89   size_t valuelen;
90   char buf[950], *p;
91   size_t n;
92   
93   va_start (arg_ptr, keyword);
94
95   p = buf; 
96   n = 0;
97   valuelen = strlen (keyword);
98   for ( ; valuelen && n < DIM (buf)-2; n++, valuelen--, keyword++)
99     *p++ = *keyword;
100
101   while ( (value = va_arg (arg_ptr, const unsigned char *)) )
102     {
103       valuelen = va_arg (arg_ptr, size_t);
104       if (!valuelen)
105         continue; /* empty buffer */
106       if (n)
107         {
108           *p++ = ' ';
109           n++;
110         }
111       for ( ; valuelen && n < DIM (buf)-2; n++, valuelen--, value++)
112         {
113           if (*value < ' ' || *value == '+')
114             {
115               sprintf (p, "%%%02X", *value);
116               p += 3;
117             }
118           else if (*value == ' ')
119             *p++ = '+';
120           else
121             *p++ = *value;
122         }
123     }
124   *p = 0;
125   ctrl->status_cb (ctrl->status_cb_arg, buf);
126
127   va_end (arg_ptr);
128 }
129
130
131 void gcry_md_hash_buffer (int algo, void *digest,
132                           const void *buffer, size_t length)
133 {
134   MD_HANDLE h = md_open (algo, 0);
135   if (!h)
136     BUG();
137   md_write (h, (byte *) buffer, length);
138   md_final (h);
139   memcpy (digest, md_read (h, algo), md_digest_length (algo));
140   md_close (h);
141 }
142
143
144 /* This is a limited version of the one in 1.9 but it should be
145    sufficient here. */
146 void
147 log_printf (const char *fmt, ...)
148 {
149   va_list arg_ptr;
150
151   va_start (arg_ptr, fmt);
152   vfprintf (log_stream (), fmt, arg_ptr);
153   va_end (arg_ptr);
154 }
155
156
157
158 /* Print a hexdump of BUFFER.  With TEXT of NULL print just the raw
159    dump, with TEXT just an empty string, print a trailing linefeed,
160    otherwise print an entire debug line. */
161 void
162 log_printhex (const char *text, const void *buffer, size_t length)
163 {
164   if (text && *text)
165     log_debug ("%s ", text);
166   if (length)
167     {
168       const unsigned char *p = buffer;
169       log_printf ("%02X", *p);
170       for (length--, p++; length--; p++)
171         log_printf (" %02X", *p);
172     }
173   if (text)
174     log_printf ("\n");
175 }
176
177
178
179 void
180 app_set_default_reader_port (const char *portstr)
181 {
182   xfree (default_reader_port);
183   default_reader_port = portstr? xstrdup (portstr): NULL;
184 }
185
186
187 /* Retrieve the serial number and the time of the last update of the
188    card.  The serial number is returned as a malloced string (hex
189    encoded) in SERIAL and the time of update is returned in STAMP.  If
190    no update time is available the returned value is 0.  Caller must
191    free SERIAL unless the function returns an error. */
192 int 
193 app_get_serial_and_stamp (APP app, char **serial, time_t *stamp)
194 {
195   unsigned char *buf, *p;
196   int i;
197
198   if (!app || !serial || !stamp)
199     return gpg_error (GPG_ERR_INV_VALUE);
200
201   *serial = NULL;
202   *stamp = 0; /* not available */
203
204   buf = xtrymalloc (app->serialnolen * 2 + 1);
205   if (!buf)
206     return gpg_error_from_errno (errno);
207   for (p=buf, i=0; i < app->serialnolen; p +=2, i++)
208     sprintf (p, "%02X", app->serialno[i]);
209   *p = 0;
210   *serial = buf;
211   return 0;
212 }
213
214
215
216
217
218
219 /* Release the card info structure. */
220 void 
221 agent_release_card_info (struct agent_card_info_s *info)
222 {
223   if (!info)
224     return;
225
226   xfree (info->serialno); info->serialno = NULL;
227   xfree (info->disp_name); info->disp_name = NULL;
228   xfree (info->disp_lang); info->disp_lang = NULL;
229   xfree (info->pubkey_url); info->pubkey_url = NULL;
230   xfree (info->login_data); info->login_data = NULL;
231   info->fpr1valid = info->fpr2valid = info->fpr3valid = 0;
232 }
233
234
235 /* Open the current card and select the openpgp application.  Return
236    an APP context handle to be used for further procesing or NULL on
237    error or if no OpenPGP application exists.*/
238 static APP
239 open_card (void)
240 {
241   int slot;
242   int rc;
243   APP app;
244
245   current_app = NULL;/* FIXME: Release it first.*/
246   slot = apdu_open_reader (default_reader_port);
247   if (slot == -1)
248     {
249       log_error ("card reader not available\n");
250       return NULL;
251     }
252
253   app = xcalloc (1, sizeof *app);
254   app->slot = slot;
255   rc = app_select_openpgp (app, &app->serialno, &app->serialnolen);
256   if (rc)
257     {
258 /*        apdu_close_reader (slot); */
259       log_info ("selecting openpgp failed: %s\n", gpg_strerror (rc));
260       xfree (app);
261       return NULL;
262     }
263
264   app->initialized = 1;
265   current_app = app;
266   return app;
267 }
268
269
270
271 /* Return a new malloced string by unescaping the string S.  Escaping
272    is percent escaping and '+'/space mapping.  A binary nul will
273    silently be replaced by a 0xFF.  Function returns NULL to indicate
274    an out of memory status. */
275 static char *
276 unescape_status_string (const unsigned char *s)
277 {
278   char *buffer, *d;
279
280   buffer = d = xmalloc (strlen (s)+1);
281   while (*s)
282     {
283       if (*s == '%' && s[1] && s[2])
284         { 
285           s++;
286           *d = xtoi_2 (s);
287           if (!*d)
288             *d = '\xff';
289           d++;
290           s += 2;
291         }
292       else if (*s == '+')
293         {
294           *d++ = ' ';
295           s++;
296         }
297       else
298         *d++ = *s++;
299     }
300   *d = 0; 
301   return buffer;
302 }
303
304 /* Take a 20 byte hexencoded string and put it into the the provided
305    20 byte buffer FPR in binary format. */
306 static int
307 unhexify_fpr (const char *hexstr, unsigned char *fpr)
308 {
309   const char *s;
310   int n;
311
312   for (s=hexstr, n=0; hexdigitp (s); s++, n++)
313     ;
314   if (*s || (n != 40))
315     return 0; /* no fingerprint (invalid or wrong length). */
316   n /= 2;
317   for (s=hexstr, n=0; *s; s += 2, n++)
318     fpr[n] = xtoi_2 (s);
319   return 1; /* okay */
320 }
321
322 /* Take the serial number from LINE and return it verbatim in a newly
323    allocated string.  We make sure that only hex characters are
324    returned. */
325 static char *
326 store_serialno (const char *line)
327 {
328   const char *s;
329   char *p;
330
331   for (s=line; hexdigitp (s); s++)
332     ;
333   p = xmalloc (s + 1 - line);
334   memcpy (p, line, s-line);
335   p[s-line] = 0;
336   return p;
337 }
338
339
340
341 static int
342 learn_status_cb (void *opaque, const char *line)
343 {
344   struct agent_card_info_s *parm = opaque;
345   const char *keyword = line;
346   int keywordlen;
347   int i;
348
349   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
350     ;
351   while (spacep (line))
352     line++;
353
354   if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
355     {
356       xfree (parm->serialno);
357       parm->serialno = store_serialno (line);
358     }
359   else if (keywordlen == 9 && !memcmp (keyword, "DISP-NAME", keywordlen))
360     {
361       xfree (parm->disp_name);
362       parm->disp_name = unescape_status_string (line);
363     }
364   else if (keywordlen == 9 && !memcmp (keyword, "DISP-LANG", keywordlen))
365     {
366       xfree (parm->disp_lang);
367       parm->disp_lang = unescape_status_string (line);
368     }
369   else if (keywordlen == 8 && !memcmp (keyword, "DISP-SEX", keywordlen))
370     {
371       parm->disp_sex = *line == '1'? 1 : *line == '2' ? 2: 0;
372     }
373   else if (keywordlen == 10 && !memcmp (keyword, "PUBKEY-URL", keywordlen))
374     {
375       xfree (parm->pubkey_url);
376       parm->pubkey_url = unescape_status_string (line);
377     }
378   else if (keywordlen == 10 && !memcmp (keyword, "LOGIN-DATA", keywordlen))
379     {
380       xfree (parm->login_data);
381       parm->login_data = unescape_status_string (line);
382     }
383   else if (keywordlen == 11 && !memcmp (keyword, "SIG-COUNTER", keywordlen))
384     {
385       parm->sig_counter = strtoul (line, NULL, 0);
386     }
387   else if (keywordlen == 10 && !memcmp (keyword, "CHV-STATUS", keywordlen))
388     {
389       char *p, *buf;
390
391       buf = p = unescape_status_string (line);
392       if (buf)
393         {
394           while (spacep (p))
395             p++;
396           parm->chv1_cached = atoi (p);
397           while (!spacep (p))
398             p++;
399           while (spacep (p))
400             p++;
401           for (i=0; *p && i < 3; i++)
402             {
403               parm->chvmaxlen[i] = atoi (p);
404               while (!spacep (p))
405                 p++;
406               while (spacep (p))
407                 p++;
408             }
409           for (i=0; *p && i < 3; i++)
410             {
411               parm->chvretry[i] = atoi (p);
412               while (!spacep (p))
413                 p++;
414               while (spacep (p))
415                 p++;
416             }
417           xfree (buf);
418         }
419     }
420   else if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
421     {
422       int no = atoi (line);
423       while (!spacep (line))
424         line++;
425       while (spacep (line))
426         line++;
427       if (no == 1)
428         parm->fpr1valid = unhexify_fpr (line, parm->fpr1);
429       else if (no == 2)
430         parm->fpr2valid = unhexify_fpr (line, parm->fpr2);
431       else if (no == 3)
432         parm->fpr3valid = unhexify_fpr (line, parm->fpr3);
433     }
434   
435   return 0;
436 }
437
438
439 /* Return card info. */
440 int 
441 agent_learn (struct agent_card_info_s *info)
442 {
443   APP app;
444   int rc;
445   struct ctrl_ctx_s ctrl;
446   time_t stamp;
447   char *serial;
448   
449   app = current_app? current_app : open_card ();
450   if (!app)
451     return gpg_error (GPG_ERR_CARD);
452
453   memset (info, 0, sizeof *info);
454   memset (&ctrl, 0, sizeof ctrl);
455   ctrl.status_cb = learn_status_cb;
456   ctrl.status_cb_arg = info;
457
458   rc = app_get_serial_and_stamp (app, &serial, &stamp);
459   if (!rc)
460     {
461       send_status_info (&ctrl, "SERIALNO", serial, strlen(serial), NULL, 0);
462       xfree (serial);
463       rc = app->fnc.learn_status (app, &ctrl);
464     }
465
466   return rc;
467 }
468
469 /* Get an attribite from the card. Make sure info is initialized. */
470 int 
471 agent_scd_getattr (const char *name, struct agent_card_info_s *info)
472 {
473   APP app;
474   struct ctrl_ctx_s ctrl;
475
476   app = current_app? current_app : open_card ();
477   if (!app)
478     return gpg_error (GPG_ERR_CARD);
479
480   ctrl.status_cb = learn_status_cb;
481   ctrl.status_cb_arg = info;
482   return app->fnc.getattr (app, &ctrl, name);
483 }
484
485
486
487 static int 
488 pin_cb (void *opaque, const char *info, char **retstr)
489 {
490   char *value;
491   int canceled;
492
493   *retstr = NULL;
494   log_debug ("asking for PIN '%s'\n", info);
495
496   value = ask_passphrase (info, "Enter PIN: ", &canceled);
497   if (!value && canceled)
498     return -1;
499   else if (!value)
500     return G10ERR_GENERAL;
501
502   *retstr = value;
503   return 0;
504 }
505
506
507
508 /* Send a SETATTR command to the SCdaemon. */
509 int 
510 agent_scd_setattr (const char *name,
511                    const unsigned char *value, size_t valuelen)
512 {
513   APP app;
514
515   app = current_app? current_app : open_card ();
516   if (!app)
517     return gpg_error (GPG_ERR_CARD);
518
519   return app->fnc.setattr (app, name, pin_cb, NULL, value, valuelen);
520 }
521
522 /* Send a GENKEY command to the SCdaemon. */
523 int 
524 agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force)
525 {
526
527   return gpg_error (GPG_ERR_CARD);
528 }
529
530 /* Send a PKSIGN command to the SCdaemon. */
531 int 
532 agent_scd_pksign (const char *serialno, int hashalgo,
533                   const unsigned char *indata, size_t indatalen,
534                   char **r_buf, size_t *r_buflen)
535 {
536   APP app;
537
538   *r_buf = NULL;
539   *r_buflen = 0;
540   app = current_app? current_app : open_card ();
541   if (!app)
542     return gpg_error (GPG_ERR_CARD);
543
544   /* Check that the card's serialnumber is as required.*/
545
546   return app->fnc.sign (app, serialno, hashalgo,
547                         pin_cb, NULL,
548                         indata, indatalen,
549                         r_buf, r_buflen);
550 }
551
552
553 /* Send a PKDECRYPT command to the SCdaemon. */
554 int 
555 agent_scd_pkdecrypt (const char *serialno,
556                      const unsigned char *indata, size_t indatalen,
557                      char **r_buf, size_t *r_buflen)
558 {
559
560   return gpg_error (GPG_ERR_CARD);
561 }
562
563 /* Change the PIN of an OpenPGP card or reset the retry counter. */
564 int 
565 agent_scd_change_pin (int chvno)
566 {
567
568   return gpg_error (GPG_ERR_CARD);
569 }
570