* cardglue.c (pin_cb): Detect whether an admin or regular PIN is
[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   current_app = NULL;/* FIXME: Release it first.*/
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
277
278 /* Return a new malloced string by unescaping the string S.  Escaping
279    is percent escaping and '+'/space mapping.  A binary nul will
280    silently be replaced by a 0xFF.  Function returns NULL to indicate
281    an out of memory status. */
282 static char *
283 unescape_status_string (const unsigned char *s)
284 {
285   char *buffer, *d;
286
287   buffer = d = xmalloc (strlen (s)+1);
288   while (*s)
289     {
290       if (*s == '%' && s[1] && s[2])
291         { 
292           s++;
293           *d = xtoi_2 (s);
294           if (!*d)
295             *d = '\xff';
296           d++;
297           s += 2;
298         }
299       else if (*s == '+')
300         {
301           *d++ = ' ';
302           s++;
303         }
304       else
305         *d++ = *s++;
306     }
307   *d = 0; 
308   return buffer;
309 }
310
311 /* Take a 20 byte hexencoded string and put it into the the provided
312    20 byte buffer FPR in binary format. */
313 static int
314 unhexify_fpr (const char *hexstr, unsigned char *fpr)
315 {
316   const char *s;
317   int n;
318
319   for (s=hexstr, n=0; hexdigitp (s); s++, n++)
320     ;
321   if (*s || (n != 40))
322     return 0; /* no fingerprint (invalid or wrong length). */
323   n /= 2;
324   for (s=hexstr, n=0; *s; s += 2, n++)
325     fpr[n] = xtoi_2 (s);
326   return 1; /* okay */
327 }
328
329 /* Take the serial number from LINE and return it verbatim in a newly
330    allocated string.  We make sure that only hex characters are
331    returned. */
332 static char *
333 store_serialno (const char *line)
334 {
335   const char *s;
336   char *p;
337
338   for (s=line; hexdigitp (s); s++)
339     ;
340   p = xmalloc (s + 1 - line);
341   memcpy (p, line, s-line);
342   p[s-line] = 0;
343   return p;
344 }
345
346
347
348 static int
349 learn_status_cb (void *opaque, const char *line)
350 {
351   struct agent_card_info_s *parm = opaque;
352   const char *keyword = line;
353   int keywordlen;
354   int i;
355
356   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
357     ;
358   while (spacep (line))
359     line++;
360
361   if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
362     {
363       xfree (parm->serialno);
364       parm->serialno = store_serialno (line);
365     }
366   else if (keywordlen == 9 && !memcmp (keyword, "DISP-NAME", keywordlen))
367     {
368       xfree (parm->disp_name);
369       parm->disp_name = unescape_status_string (line);
370     }
371   else if (keywordlen == 9 && !memcmp (keyword, "DISP-LANG", keywordlen))
372     {
373       xfree (parm->disp_lang);
374       parm->disp_lang = unescape_status_string (line);
375     }
376   else if (keywordlen == 8 && !memcmp (keyword, "DISP-SEX", keywordlen))
377     {
378       parm->disp_sex = *line == '1'? 1 : *line == '2' ? 2: 0;
379     }
380   else if (keywordlen == 10 && !memcmp (keyword, "PUBKEY-URL", keywordlen))
381     {
382       xfree (parm->pubkey_url);
383       parm->pubkey_url = unescape_status_string (line);
384     }
385   else if (keywordlen == 10 && !memcmp (keyword, "LOGIN-DATA", keywordlen))
386     {
387       xfree (parm->login_data);
388       parm->login_data = unescape_status_string (line);
389     }
390   else if (keywordlen == 11 && !memcmp (keyword, "SIG-COUNTER", keywordlen))
391     {
392       parm->sig_counter = strtoul (line, NULL, 0);
393     }
394   else if (keywordlen == 10 && !memcmp (keyword, "CHV-STATUS", keywordlen))
395     {
396       char *p, *buf;
397
398       buf = p = unescape_status_string (line);
399       if (buf)
400         {
401           while (spacep (p))
402             p++;
403           parm->chv1_cached = atoi (p);
404           while (!spacep (p))
405             p++;
406           while (spacep (p))
407             p++;
408           for (i=0; *p && i < 3; i++)
409             {
410               parm->chvmaxlen[i] = atoi (p);
411               while (!spacep (p))
412                 p++;
413               while (spacep (p))
414                 p++;
415             }
416           for (i=0; *p && i < 3; i++)
417             {
418               parm->chvretry[i] = atoi (p);
419               while (!spacep (p))
420                 p++;
421               while (spacep (p))
422                 p++;
423             }
424           xfree (buf);
425         }
426     }
427   else if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
428     {
429       int no = atoi (line);
430       while (!spacep (line))
431         line++;
432       while (spacep (line))
433         line++;
434       if (no == 1)
435         parm->fpr1valid = unhexify_fpr (line, parm->fpr1);
436       else if (no == 2)
437         parm->fpr2valid = unhexify_fpr (line, parm->fpr2);
438       else if (no == 3)
439         parm->fpr3valid = unhexify_fpr (line, parm->fpr3);
440     }
441   
442   return 0;
443 }
444
445
446 /* Return card info. */
447 int 
448 agent_learn (struct agent_card_info_s *info)
449 {
450   APP app;
451   int rc;
452   struct ctrl_ctx_s ctrl;
453   time_t stamp;
454   char *serial;
455   
456   app = current_app? current_app : open_card ();
457   if (!app)
458     return gpg_error (GPG_ERR_CARD);
459
460   memset (info, 0, sizeof *info);
461   memset (&ctrl, 0, sizeof ctrl);
462   ctrl.status_cb = learn_status_cb;
463   ctrl.status_cb_arg = info;
464
465   rc = app_get_serial_and_stamp (app, &serial, &stamp);
466   if (!rc)
467     {
468       send_status_info (&ctrl, "SERIALNO", serial, strlen(serial), NULL, 0);
469       xfree (serial);
470       rc = app->fnc.learn_status (app, &ctrl);
471     }
472
473   return rc;
474 }
475
476 /* Get an attribite from the card. Make sure info is initialized. */
477 int 
478 agent_scd_getattr (const char *name, struct agent_card_info_s *info)
479 {
480   APP app;
481   struct ctrl_ctx_s ctrl;
482
483   app = current_app? current_app : open_card ();
484   if (!app)
485     return gpg_error (GPG_ERR_CARD);
486
487   ctrl.status_cb = learn_status_cb;
488   ctrl.status_cb_arg = info;
489   return app->fnc.getattr (app, &ctrl, name);
490 }
491
492
493
494 static int 
495 pin_cb (void *opaque, const char *info, char **retstr)
496 {
497   char *value;
498   int canceled;
499
500   *retstr = NULL;
501   log_debug ("asking for PIN '%s'\n", info);
502
503   value = ask_passphrase (info, 
504                           info && strstr (info, "dmin")?
505                            _("Enter Admin PIN: ") : _("Enter PIN: "),
506                           &canceled);
507   if (!value && canceled)
508     return -1;
509   else if (!value)
510     return G10ERR_GENERAL;
511
512   *retstr = value;
513   return 0;
514 }
515
516
517
518 /* Send a SETATTR command to the SCdaemon. */
519 int 
520 agent_scd_setattr (const char *name,
521                    const unsigned char *value, size_t valuelen)
522 {
523   APP app;
524
525   app = current_app? current_app : open_card ();
526   if (!app)
527     return gpg_error (GPG_ERR_CARD);
528
529   return app->fnc.setattr (app, name, pin_cb, NULL, value, valuelen);
530 }
531
532
533 static int
534 genkey_status_cb (void *opaque, const char *line)
535 {
536   struct agent_card_genkey_s *parm = opaque;
537   const char *keyword = line;
538   int keywordlen;
539
540   log_debug ("got status line `%s'\n", line);
541   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
542     ;
543   while (spacep (line))
544     line++;
545
546   if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
547     {
548       parm->fprvalid = unhexify_fpr (line, parm->fpr);
549     }
550   if (keywordlen == 8 && !memcmp (keyword, "KEY-DATA", keywordlen))
551     {
552       MPI a;
553       const char *name = line;
554       char *buf;
555
556       while (!spacep (line))
557         line++;
558       while (spacep (line))
559         line++;
560
561       buf = xmalloc ( 2 + strlen (line) + 1);
562       strcpy (stpcpy (buf, "0x"), line);
563       a = mpi_alloc (300);
564       if( mpi_fromstr (a, buf) )
565         log_error ("error parsing received key data\n");
566       else if (*name == 'n' && spacep (name+1))
567         parm->n = a;
568       else if (*name == 'e' && spacep (name+1))
569         parm->e = a;
570       else
571         {
572           log_info ("unknown parameter name in received key data\n");
573           mpi_free (a);
574         }
575       xfree (buf);
576     }
577   else if (keywordlen == 14 && !memcmp (keyword,"KEY-CREATED-AT", keywordlen))
578     {
579       parm->created_at = (u32)strtoul (line, NULL, 10);
580     }
581
582   return 0;
583 }
584
585 /* Send a GENKEY command to the SCdaemon. */
586 int 
587 agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force)
588 {
589   APP app;
590   char keynostr[20];
591   struct ctrl_ctx_s ctrl;
592
593   app = current_app? current_app : open_card ();
594   if (!app)
595     return gpg_error (GPG_ERR_CARD);
596
597   memset (info, 0, sizeof *info);
598   sprintf (keynostr, "%d", keyno);
599   ctrl.status_cb = genkey_status_cb;
600   ctrl.status_cb_arg = info;
601
602   return app->fnc.genkey (app, &ctrl, keynostr,
603                            force? 1:0,
604                            pin_cb, NULL);
605 }
606
607 /* Send a PKSIGN command to the SCdaemon. */
608 int 
609 agent_scd_pksign (const char *serialno, int hashalgo,
610                   const unsigned char *indata, size_t indatalen,
611                   unsigned char **r_buf, size_t *r_buflen)
612 {
613   APP app;
614
615   *r_buf = NULL;
616   *r_buflen = 0;
617   app = current_app? current_app : open_card ();
618   if (!app)
619     return gpg_error (GPG_ERR_CARD);
620
621   /* Check that the card's serialnumber is as required.*/
622
623   return app->fnc.sign (app, serialno, hashalgo,
624                         pin_cb, NULL,
625                         indata, indatalen,
626                         r_buf, r_buflen);
627 }
628
629
630 /* Send a PKDECRYPT command to the SCdaemon. */
631 int 
632 agent_scd_pkdecrypt (const char *serialno,
633                      const unsigned char *indata, size_t indatalen,
634                      char **r_buf, size_t *r_buflen)
635 {
636
637   return gpg_error (GPG_ERR_CARD);
638 }
639
640 /* Change the PIN of an OpenPGP card or reset the retry counter. */
641 int 
642 agent_scd_change_pin (int chvno)
643 {
644
645   return gpg_error (GPG_ERR_CARD);
646 }
647