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