3173248cb8cf71bf996a4b987d428826722fd4b5
[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 (*p && !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 (*p && !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 (*p && !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 (* line && !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   int isadmin = (info && strstr (info, "dmin"));
512
513
514   *retstr = NULL;
515   log_debug ("asking for PIN '%s'\n", info);
516
517   value = ask_passphrase (info, 
518                           isadmin? "passphrase.adminpin.ask"
519                                  : "passphrase.pin.ask", 
520                           isadmin?  _("Enter Admin PIN: ") : _("Enter PIN: "),
521                           &canceled);
522   if (!value && canceled)
523     return -1;
524   else if (!value)
525     return G10ERR_GENERAL;
526
527   *retstr = value;
528   return 0;
529 }
530
531
532
533 /* Send a SETATTR command to the SCdaemon. */
534 int 
535 agent_scd_setattr (const char *name,
536                    const unsigned char *value, size_t valuelen)
537 {
538   APP app;
539
540   app = current_app? current_app : open_card ();
541   if (!app)
542     return gpg_error (GPG_ERR_CARD);
543
544   return app->fnc.setattr (app, name, pin_cb, NULL, value, valuelen);
545 }
546
547
548 static int
549 genkey_status_cb (void *opaque, const char *line)
550 {
551   struct agent_card_genkey_s *parm = opaque;
552   const char *keyword = line;
553   int keywordlen;
554
555   log_debug ("got status line `%s'\n", line);
556   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
557     ;
558   while (spacep (line))
559     line++;
560
561   if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
562     {
563       parm->fprvalid = unhexify_fpr (line, parm->fpr);
564     }
565   if (keywordlen == 8 && !memcmp (keyword, "KEY-DATA", keywordlen))
566     {
567       MPI a;
568       const char *name = line;
569       char *buf;
570
571       while (*line && !spacep (line))
572         line++;
573       while (spacep (line))
574         line++;
575
576       buf = xmalloc ( 2 + strlen (line) + 1);
577       strcpy (stpcpy (buf, "0x"), line);
578       a = mpi_alloc (300);
579       if( mpi_fromstr (a, buf) )
580         log_error ("error parsing received key data\n");
581       else if (*name == 'n' && spacep (name+1))
582         parm->n = a;
583       else if (*name == 'e' && spacep (name+1))
584         parm->e = a;
585       else
586         {
587           log_info ("unknown parameter name in received key data\n");
588           mpi_free (a);
589         }
590       xfree (buf);
591     }
592   else if (keywordlen == 14 && !memcmp (keyword,"KEY-CREATED-AT", keywordlen))
593     {
594       parm->created_at = (u32)strtoul (line, NULL, 10);
595     }
596
597   return 0;
598 }
599
600 /* Send a GENKEY command to the SCdaemon. */
601 int 
602 agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force)
603 {
604   APP app;
605   char keynostr[20];
606   struct ctrl_ctx_s ctrl;
607
608   app = current_app? current_app : open_card ();
609   if (!app)
610     return gpg_error (GPG_ERR_CARD);
611
612   memset (info, 0, sizeof *info);
613   sprintf (keynostr, "%d", keyno);
614   ctrl.status_cb = genkey_status_cb;
615   ctrl.status_cb_arg = info;
616
617   return app->fnc.genkey (app, &ctrl, keynostr,
618                            force? 1:0,
619                            pin_cb, NULL);
620 }
621
622 /* Send a PKSIGN command to the SCdaemon. */
623 int 
624 agent_scd_pksign (const char *serialno, int hashalgo,
625                   const unsigned char *indata, size_t indatalen,
626                   unsigned char **r_buf, size_t *r_buflen)
627 {
628   APP app;
629
630   *r_buf = NULL;
631   *r_buflen = 0;
632   app = current_app? current_app : open_card ();
633   if (!app)
634     return gpg_error (GPG_ERR_CARD);
635
636   /* Check that the card's serialnumber is as required.*/
637
638   return app->fnc.sign (app, serialno, hashalgo,
639                         pin_cb, NULL,
640                         indata, indatalen,
641                         r_buf, r_buflen);
642 }
643
644
645 /* Send a PKDECRYPT command to the SCdaemon. */
646 int 
647 agent_scd_pkdecrypt (const char *serialno,
648                      const unsigned char *indata, size_t indatalen,
649                      unsigned char **r_buf, size_t *r_buflen)
650 {
651   APP app;
652
653   *r_buf = NULL;
654   *r_buflen = 0;
655   app = current_app? current_app : open_card ();
656   if (!app)
657     return gpg_error (GPG_ERR_CARD);
658
659   return app->fnc.decipher (app, serialno, 
660                             pin_cb, NULL,
661                             indata, indatalen,
662                             r_buf, r_buflen);
663 }
664
665 /* Change the PIN of an OpenPGP card or reset the retry counter. */
666 int 
667 agent_scd_change_pin (int chvno)
668 {
669   APP app;
670   char chvnostr[20];
671   int reset = 0;
672
673   reset = (chvno >= 100);
674   chvno %= 100;
675
676   app = current_app? current_app : open_card ();
677   if (!app)
678     return gpg_error (GPG_ERR_CARD);
679
680   sprintf (chvnostr, "%d", chvno);
681   return app->fnc.change_pin (app, NULL, chvnostr, reset,
682                               pin_cb, NULL);
683 }
684
685 /* Perform a CHECKPIN operation.  SERIALNO should be the seriial
686    number of the card - optioanlly followed by the fingerprint;
687    however the fingerprint is ignored here. */
688 int
689 agent_scd_checkpin (const char *serialnobuf)
690 {
691   APP app;
692
693   app = current_app? current_app : open_card ();
694   if (!app)
695     return gpg_error (GPG_ERR_CARD);
696
697   return app->fnc.check_pin (app, serialnobuf, pin_cb, NULL);
698 }
699