* cardglue.c (card_close): New.
[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 void
188 card_set_reader_port (const char *portstr)
189 {
190   app_set_default_reader_port (portstr);
191 }
192
193
194 /* Retrieve the serial number and the time of the last update of the
195    card.  The serial number is returned as a malloced string (hex
196    encoded) in SERIAL and the time of update is returned in STAMP.  If
197    no update time is available the returned value is 0.  Caller must
198    free SERIAL unless the function returns an error. */
199 int 
200 app_get_serial_and_stamp (APP app, char **serial, time_t *stamp)
201 {
202   unsigned char *buf, *p;
203   int i;
204
205   if (!app || !serial || !stamp)
206     return gpg_error (GPG_ERR_INV_VALUE);
207
208   *serial = NULL;
209   *stamp = 0; /* not available */
210
211   buf = xtrymalloc (app->serialnolen * 2 + 1);
212   if (!buf)
213     return gpg_error_from_errno (errno);
214   for (p=buf, i=0; i < app->serialnolen; p +=2, i++)
215     sprintf (p, "%02X", app->serialno[i]);
216   *p = 0;
217   *serial = buf;
218   return 0;
219 }
220
221
222
223
224
225
226 /* Release the card info structure. */
227 void 
228 agent_release_card_info (struct agent_card_info_s *info)
229 {
230   if (!info)
231     return;
232
233   xfree (info->serialno); info->serialno = NULL;
234   xfree (info->disp_name); info->disp_name = NULL;
235   xfree (info->disp_lang); info->disp_lang = NULL;
236   xfree (info->pubkey_url); info->pubkey_url = NULL;
237   xfree (info->login_data); info->login_data = NULL;
238   info->fpr1valid = info->fpr2valid = info->fpr3valid = 0;
239 }
240
241
242 /* Open the current card and select the openpgp application.  Return
243    an APP context handle to be used for further procesing or NULL on
244    error or if no OpenPGP application exists.*/
245 static APP
246 open_card (void)
247 {
248   int slot;
249   int rc;
250   APP app;
251
252   card_close ();
253   slot = apdu_open_reader (default_reader_port);
254   if (slot == -1)
255     {
256       log_error ("card reader not available\n");
257       return NULL;
258     }
259
260   app = xcalloc (1, sizeof *app);
261   app->slot = slot;
262   rc = app_select_openpgp (app, &app->serialno, &app->serialnolen);
263   if (rc)
264     {
265       apdu_close_reader (slot);
266       log_info ("selecting openpgp failed: %s\n", gpg_strerror (rc));
267       xfree (app);
268       return NULL;
269     }
270
271   app->initialized = 1;
272   current_app = app;
273   return app;
274 }
275
276 void
277 card_close (void)
278 {
279   if (current_app)
280     {
281       APP app = current_app;
282       current_app = NULL;
283
284       apdu_close_reader (app->slot);
285       xfree (app);
286     }
287 }
288
289
290 /* Return a new malloced string by unescaping the string S.  Escaping
291    is percent escaping and '+'/space mapping.  A binary nul will
292    silently be replaced by a 0xFF.  Function returns NULL to indicate
293    an out of memory status. */
294 static char *
295 unescape_status_string (const unsigned char *s)
296 {
297   char *buffer, *d;
298
299   buffer = d = xmalloc (strlen (s)+1);
300   while (*s)
301     {
302       if (*s == '%' && s[1] && s[2])
303         { 
304           s++;
305           *d = xtoi_2 (s);
306           if (!*d)
307             *d = '\xff';
308           d++;
309           s += 2;
310         }
311       else if (*s == '+')
312         {
313           *d++ = ' ';
314           s++;
315         }
316       else
317         *d++ = *s++;
318     }
319   *d = 0; 
320   return buffer;
321 }
322
323 /* Take a 20 byte hexencoded string and put it into the the provided
324    20 byte buffer FPR in binary format. */
325 static int
326 unhexify_fpr (const char *hexstr, unsigned char *fpr)
327 {
328   const char *s;
329   int n;
330
331   for (s=hexstr, n=0; hexdigitp (s); s++, n++)
332     ;
333   if (*s || (n != 40))
334     return 0; /* no fingerprint (invalid or wrong length). */
335   n /= 2;
336   for (s=hexstr, n=0; *s; s += 2, n++)
337     fpr[n] = xtoi_2 (s);
338   return 1; /* okay */
339 }
340
341 /* Take the serial number from LINE and return it verbatim in a newly
342    allocated string.  We make sure that only hex characters are
343    returned. */
344 static char *
345 store_serialno (const char *line)
346 {
347   const char *s;
348   char *p;
349
350   for (s=line; hexdigitp (s); s++)
351     ;
352   p = xmalloc (s + 1 - line);
353   memcpy (p, line, s-line);
354   p[s-line] = 0;
355   return p;
356 }
357
358
359
360 static int
361 learn_status_cb (void *opaque, const char *line)
362 {
363   struct agent_card_info_s *parm = opaque;
364   const char *keyword = line;
365   int keywordlen;
366   int i;
367
368   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
369     ;
370   while (spacep (line))
371     line++;
372
373   if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
374     {
375       xfree (parm->serialno);
376       parm->serialno = store_serialno (line);
377     }
378   else if (keywordlen == 9 && !memcmp (keyword, "DISP-NAME", keywordlen))
379     {
380       xfree (parm->disp_name);
381       parm->disp_name = unescape_status_string (line);
382     }
383   else if (keywordlen == 9 && !memcmp (keyword, "DISP-LANG", keywordlen))
384     {
385       xfree (parm->disp_lang);
386       parm->disp_lang = unescape_status_string (line);
387     }
388   else if (keywordlen == 8 && !memcmp (keyword, "DISP-SEX", keywordlen))
389     {
390       parm->disp_sex = *line == '1'? 1 : *line == '2' ? 2: 0;
391     }
392   else if (keywordlen == 10 && !memcmp (keyword, "PUBKEY-URL", keywordlen))
393     {
394       xfree (parm->pubkey_url);
395       parm->pubkey_url = unescape_status_string (line);
396     }
397   else if (keywordlen == 10 && !memcmp (keyword, "LOGIN-DATA", keywordlen))
398     {
399       xfree (parm->login_data);
400       parm->login_data = unescape_status_string (line);
401     }
402   else if (keywordlen == 11 && !memcmp (keyword, "SIG-COUNTER", keywordlen))
403     {
404       parm->sig_counter = strtoul (line, NULL, 0);
405     }
406   else if (keywordlen == 10 && !memcmp (keyword, "CHV-STATUS", keywordlen))
407     {
408       char *p, *buf;
409
410       buf = p = unescape_status_string (line);
411       if (buf)
412         {
413           while (spacep (p))
414             p++;
415           parm->chv1_cached = atoi (p);
416           while (!spacep (p))
417             p++;
418           while (spacep (p))
419             p++;
420           for (i=0; *p && i < 3; i++)
421             {
422               parm->chvmaxlen[i] = atoi (p);
423               while (!spacep (p))
424                 p++;
425               while (spacep (p))
426                 p++;
427             }
428           for (i=0; *p && i < 3; i++)
429             {
430               parm->chvretry[i] = atoi (p);
431               while (!spacep (p))
432                 p++;
433               while (spacep (p))
434                 p++;
435             }
436           xfree (buf);
437         }
438     }
439   else if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
440     {
441       int no = atoi (line);
442       while (!spacep (line))
443         line++;
444       while (spacep (line))
445         line++;
446       if (no == 1)
447         parm->fpr1valid = unhexify_fpr (line, parm->fpr1);
448       else if (no == 2)
449         parm->fpr2valid = unhexify_fpr (line, parm->fpr2);
450       else if (no == 3)
451         parm->fpr3valid = unhexify_fpr (line, parm->fpr3);
452     }
453   
454   return 0;
455 }
456
457
458 /* Return card info. */
459 int 
460 agent_learn (struct agent_card_info_s *info)
461 {
462   APP app;
463   int rc;
464   struct ctrl_ctx_s ctrl;
465   time_t stamp;
466   char *serial;
467   
468   app = current_app? current_app : open_card ();
469   if (!app)
470     return gpg_error (GPG_ERR_CARD);
471
472   memset (info, 0, sizeof *info);
473   memset (&ctrl, 0, sizeof ctrl);
474   ctrl.status_cb = learn_status_cb;
475   ctrl.status_cb_arg = info;
476
477   rc = app_get_serial_and_stamp (app, &serial, &stamp);
478   if (!rc)
479     {
480       send_status_info (&ctrl, "SERIALNO", serial, strlen(serial), NULL, 0);
481       xfree (serial);
482       rc = app->fnc.learn_status (app, &ctrl);
483     }
484
485   return rc;
486 }
487
488 /* Get an attribite from the card. Make sure info is initialized. */
489 int 
490 agent_scd_getattr (const char *name, struct agent_card_info_s *info)
491 {
492   APP app;
493   struct ctrl_ctx_s ctrl;
494
495   app = current_app? current_app : open_card ();
496   if (!app)
497     return gpg_error (GPG_ERR_CARD);
498
499   ctrl.status_cb = learn_status_cb;
500   ctrl.status_cb_arg = info;
501   return app->fnc.getattr (app, &ctrl, name);
502 }
503
504
505
506 static int 
507 pin_cb (void *opaque, const char *info, char **retstr)
508 {
509   char *value;
510   int canceled;
511
512   *retstr = NULL;
513   log_debug ("asking for PIN '%s'\n", info);
514
515   value = ask_passphrase (info, 
516                           info && strstr (info, "dmin")?
517                            _("Enter Admin PIN: ") : _("Enter PIN: "),
518                           &canceled);
519   if (!value && canceled)
520     return -1;
521   else if (!value)
522     return G10ERR_GENERAL;
523
524   *retstr = value;
525   return 0;
526 }
527
528
529
530 /* Send a SETATTR command to the SCdaemon. */
531 int 
532 agent_scd_setattr (const char *name,
533                    const unsigned char *value, size_t valuelen)
534 {
535   APP app;
536
537   app = current_app? current_app : open_card ();
538   if (!app)
539     return gpg_error (GPG_ERR_CARD);
540
541   return app->fnc.setattr (app, name, pin_cb, NULL, value, valuelen);
542 }
543
544
545 static int
546 genkey_status_cb (void *opaque, const char *line)
547 {
548   struct agent_card_genkey_s *parm = opaque;
549   const char *keyword = line;
550   int keywordlen;
551
552   log_debug ("got status line `%s'\n", line);
553   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
554     ;
555   while (spacep (line))
556     line++;
557
558   if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
559     {
560       parm->fprvalid = unhexify_fpr (line, parm->fpr);
561     }
562   if (keywordlen == 8 && !memcmp (keyword, "KEY-DATA", keywordlen))
563     {
564       MPI a;
565       const char *name = line;
566       char *buf;
567
568       while (!spacep (line))
569         line++;
570       while (spacep (line))
571         line++;
572
573       buf = xmalloc ( 2 + strlen (line) + 1);
574       strcpy (stpcpy (buf, "0x"), line);
575       a = mpi_alloc (300);
576       if( mpi_fromstr (a, buf) )
577         log_error ("error parsing received key data\n");
578       else if (*name == 'n' && spacep (name+1))
579         parm->n = a;
580       else if (*name == 'e' && spacep (name+1))
581         parm->e = a;
582       else
583         {
584           log_info ("unknown parameter name in received key data\n");
585           mpi_free (a);
586         }
587       xfree (buf);
588     }
589   else if (keywordlen == 14 && !memcmp (keyword,"KEY-CREATED-AT", keywordlen))
590     {
591       parm->created_at = (u32)strtoul (line, NULL, 10);
592     }
593
594   return 0;
595 }
596
597 /* Send a GENKEY command to the SCdaemon. */
598 int 
599 agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force)
600 {
601   APP app;
602   char keynostr[20];
603   struct ctrl_ctx_s ctrl;
604
605   app = current_app? current_app : open_card ();
606   if (!app)
607     return gpg_error (GPG_ERR_CARD);
608
609   memset (info, 0, sizeof *info);
610   sprintf (keynostr, "%d", keyno);
611   ctrl.status_cb = genkey_status_cb;
612   ctrl.status_cb_arg = info;
613
614   return app->fnc.genkey (app, &ctrl, keynostr,
615                            force? 1:0,
616                            pin_cb, NULL);
617 }
618
619 /* Send a PKSIGN command to the SCdaemon. */
620 int 
621 agent_scd_pksign (const char *serialno, int hashalgo,
622                   const unsigned char *indata, size_t indatalen,
623                   unsigned char **r_buf, size_t *r_buflen)
624 {
625   APP app;
626
627   *r_buf = NULL;
628   *r_buflen = 0;
629   app = current_app? current_app : open_card ();
630   if (!app)
631     return gpg_error (GPG_ERR_CARD);
632
633   /* Check that the card's serialnumber is as required.*/
634
635   return app->fnc.sign (app, serialno, hashalgo,
636                         pin_cb, NULL,
637                         indata, indatalen,
638                         r_buf, r_buflen);
639 }
640
641
642 /* Send a PKDECRYPT command to the SCdaemon. */
643 int 
644 agent_scd_pkdecrypt (const char *serialno,
645                      const unsigned char *indata, size_t indatalen,
646                      unsigned char **r_buf, size_t *r_buflen)
647 {
648
649   APP app;
650
651   *r_buf = NULL;
652   *r_buflen = 0;
653   app = current_app? current_app : open_card ();
654   if (!app)
655     return gpg_error (GPG_ERR_CARD);
656
657   return app->fnc.decipher (app, serialno, 
658                             pin_cb, NULL,
659                             indata, indatalen,
660                             r_buf, r_buflen);
661 }
662
663 /* Change the PIN of an OpenPGP card or reset the retry counter. */
664 int 
665 agent_scd_change_pin (int chvno)
666 {
667
668   return gpg_error (GPG_ERR_CARD);
669 }
670