Key generation and signing using the OpenPGP card does rudimentary work.
[gnupg.git] / scd / apdu.c
1 /* apdu.c - ISO 7816 APDU functions and low level I/O
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 #include <errno.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <dlfcn.h>
27 #include <assert.h>
28
29 #include "scdaemon.h"
30 #include "apdu.h"
31
32 #define HAVE_CTAPI 1
33
34 #define MAX_READER 4 /* Number of readers we support concurrently. */
35 #define CARD_CONNECT_TIMEOUT 30 /* Number of seconds to wait for
36                                    insertion of the card. */
37
38
39
40 /* A global table to keep track of active readers. */
41 static struct {
42   int used;            /* True if slot is used. */
43   unsigned short port; /* port number0 = unused, 1 - dev/tty */
44   int status;
45   unsigned char atr[33];
46   size_t atrlen;
47 } reader_table[MAX_READER];                          
48
49
50 /* ct API function pointer. */
51 static char (*CT_init) (unsigned short ctn, unsigned short Pn);
52 static char (*CT_data) (unsigned short ctn, unsigned char *dad,
53                         unsigned char *sad, unsigned short lc,
54                         unsigned char *cmd, unsigned short *lr,
55                         unsigned char *rsp);
56 static char (*CT_close) (unsigned short ctn);
57
58
59
60
61 \f
62 /* 
63       Helper
64  */
65  
66
67 /* Find an unused reader slot for PORT and put it into the reader
68    table.  Return -1 on error or the index into the reader table. */
69 static int 
70 new_reader_slot (int port)    
71 {
72   int i, reader = -1;
73
74   if (port < 0 || port > 0xffff)
75     {
76       log_error ("new_reader_slot: invalid port %d requested\n", port);
77       return -1;
78     }
79
80   for (i=0; i < MAX_READER; i++)
81     {
82       if (reader_table[i].used && reader_table[i].port == port)
83         {
84           log_error ("new_reader_slot: requested port %d already in use\n",
85                      reader);
86           return -1; 
87         }
88       else if (!reader_table[i].used && reader == -1)
89         reader = i;
90     }
91   if (reader == -1)
92     {
93       log_error ("new_reader_slot: out of slots\n");
94       return -1;
95     }
96   reader_table[reader].used = 1;
97   reader_table[reader].port = port;
98   return reader;
99 }
100
101
102 static void
103 dump_reader_status (int reader)
104 {
105   log_info ("reader %d: %s\n", reader,
106             reader_table[reader].status == 1? "Processor ICC present" :
107             reader_table[reader].status == 0? "Memory ICC present" :
108                                               "ICC not present" );
109  
110   if (reader_table[reader].status != -1)
111     {
112       log_info ("reader %d: ATR=", reader);
113       log_printhex ("", reader_table[reader].atr,
114                     reader_table[reader].atrlen);
115     }
116 }
117
118
119 \f
120 #ifdef HAVE_CTAPI
121 /* 
122        ct API Interface 
123  */
124
125 static const char *
126 ct_error_string (int err)
127 {
128   switch (err)
129     {
130     case 0: return "okay";
131     case -1: return "invalid data";
132     case -8: return "ct error";
133     case -10: return "transmission error";
134     case -11: return "memory allocation error";
135     case -128: return "HTSI error";
136     default: return "unknown CT-API error";
137     }
138 }
139
140 /* Wait for the card in READER and activate it.  Return -1 on error or
141    0 on success. */
142 static int
143 ct_activate_card (int reader)
144 {
145   int rc, count;
146
147   for (count = 0; count < CARD_CONNECT_TIMEOUT; count++)
148     {
149       unsigned char dad[1], sad[1], cmd[11], buf[256];
150       unsigned short buflen;
151
152       /* Check whether card has been inserted. */
153       dad[0] = 1;     /* Destination address: CT. */    
154       sad[0] = 2;     /* Source address: Host. */
155
156       cmd[0] = 0x20;  /* Class byte. */
157       cmd[1] = 0x13;  /* Request status. */
158       cmd[2] = 0x00;  /* From kernel. */
159       cmd[3] = 0x80;  /* Return card's DO. */
160       cmd[4] = 0x00;
161
162       buflen = DIM(buf);
163
164       rc = CT_data (reader, dad, sad, 5, cmd, &buflen, buf);
165       if (rc || buflen < 2 || buf[buflen-2] != 0x90)
166         {
167           log_error ("ct_activate_card: can't get status of reader %d: %s\n",
168                      reader, ct_error_string (rc));
169           return -1;
170         }
171
172       if (buf[0] == 0x05)
173         { /* Connected, now activate the card. */           
174           dad[0] = 1;    /* Destination address: CT. */    
175           sad[0] = 2;    /* Source address: Host. */
176
177           cmd[0] = 0x20;  /* Class byte. */
178           cmd[1] = 0x12;  /* Request ICC. */
179           cmd[2] = 0x01;  /* From first interface. */
180           cmd[3] = 0x01;  /* Return card's ATR. */
181           cmd[4] = 0x00;
182
183           buflen = DIM(buf);
184
185           rc = CT_data (reader, dad, sad, 5, cmd, &buflen, buf);
186           if (rc || buflen < 2 || buf[buflen-2] != 0x90)
187             {
188               log_error ("ct_activate_card(%d): activation failed: %s\n",
189                          reader, ct_error_string (rc));
190               return -1;
191             }
192
193           /* Store the type and the ATR. */
194           if (buflen - 2 > DIM (reader_table[0].atr))
195             {
196               log_error ("ct_activate_card(%d): ATR too long\n", reader);
197               return -1;
198             }
199
200           reader_table[reader].status = buf[buflen - 1];
201           memcpy (reader_table[reader].atr, buf, buflen - 2);
202           reader_table[reader].atrlen = buflen - 2;
203           return 0;
204         }
205
206       sleep (1); /* FIXME: we should use a more reliable timer. */
207     }
208  
209   log_info ("ct_activate_card(%d): timeout waiting for card\n", reader);
210   return -1;
211 }
212
213
214 /* Open a reader and return an internal handle for it.  PORT is a
215    non-negative value with the port number of the reader. USB readers
216    do habe port numbers starting at 32769. */
217 static int
218 open_ct_reader (int port)
219 {
220   int rc, reader;
221
222   reader = new_reader_slot (port);
223   if (reader == -1)
224     return reader;
225
226   rc = CT_init (reader, (unsigned short)port);
227   if (rc)
228     {
229       log_error ("apdu_open_ct_reader failed on port %d: %s\n",
230                  port, ct_error_string (rc));
231       reader_table[reader].used = 0;
232       return -1;
233     }
234
235   rc = ct_activate_card (reader);
236   if (rc)
237     {
238       reader_table[reader].used = 0;
239       return -1;
240     }
241
242   dump_reader_status (reader);
243   return reader;
244 }
245
246
247 /* Actuall send the APDU of length APDULEN to SLOT and return a
248    maximum of *BUFLEN data in BUFFER, the actual retruned size will be
249    set to BUFLEN.  Returns: CT API error code. */
250 static int
251 ct_send_apdu (int slot, unsigned char *apdu, size_t apdulen,
252               unsigned char *buffer, size_t *buflen)
253 {
254   int rc;
255   unsigned char dad[1], sad[1];
256   unsigned short ctbuflen;
257   
258   dad[0] = 0;     /* Destination address: Card. */    
259   sad[0] = 2;     /* Source address: Host. */
260   ctbuflen = *buflen;
261   if (DBG_CARD_IO)
262     log_printhex ("  CT_data:", apdu, apdulen);
263   rc = CT_data (slot, dad, sad, apdulen, apdu, &ctbuflen, buffer);
264   *buflen = ctbuflen;
265
266   /* FIXME: map the errorcodes to GNUPG ones, so that they can be
267      shared between CTAPI and PCSC. */
268   return rc;
269 }
270
271
272 #endif /*HAVE_CTAPI*/
273
274 \f
275 #ifdef HAVE_PCSC
276 /* 
277        PC/SC Interface
278  */
279
280
281 #endif /*HAVE_PCSC*/
282
283 \f
284 /* 
285        Driver Access
286  */
287
288 /* Open the reader and return an internal slot number or -1 on
289    error. */
290 int
291 apdu_open_reader (int port)
292 {
293   static int ct_api_loaded;
294
295   if (!ct_api_loaded)
296     {
297       void *handle;
298
299       handle = dlopen ("libtowitoko.so", RTLD_LAZY);
300       if (!handle)
301         {
302           log_error ("apdu_open_reader: failed to open driver: %s",
303                      dlerror ());
304           return -1;
305         }
306       CT_init = dlsym (handle, "CT_init");
307       CT_data = dlsym (handle, "CT_data");
308       CT_close = dlsym (handle, "CT_close");
309       if (!CT_init || !CT_data || !CT_close)
310         {
311           log_error ("apdu_open_reader: invalid driver\n");
312           dlclose (handle);
313           return -1;
314         }
315       ct_api_loaded = 1;
316     }
317   return open_ct_reader (port);
318 }
319
320
321 unsigned char *
322 apdu_get_atr (int slot, size_t *atrlen)
323 {
324   char *buf;
325
326   if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
327     return NULL;
328   
329   buf = xtrymalloc (reader_table[slot].atrlen);
330   if (!buf)
331     return NULL;
332   memcpy (buf, reader_table[slot].atr, reader_table[slot].atrlen);
333   *atrlen = reader_table[slot].atrlen;
334   return buf;
335 }
336   
337     
338 static const char *
339 error_string (int slot, int rc)
340 {
341 #ifdef HAVE_CTAPI
342   return ct_error_string (rc);
343 #elif defined(HAVE_PCSC)
344   return "?";
345 #else
346   return "?";
347 #endif
348 }
349
350
351 /* Dispatcher for the actual send_apdu fucntion. */
352 static int
353 send_apdu (int slot, unsigned char *apdu, size_t apdulen,
354            unsigned char *buffer, size_t *buflen)
355 {
356 #ifdef HAVE_CTAPI
357   return ct_send_apdu (slot, apdu, apdulen, buffer, buflen);
358 #elif defined(HAVE_PCSC)
359   return -1;
360 #else
361   return -1;
362 #endif
363 }
364
365 /* Send an APDU to the card in SLOT.  The APDU is created from all
366    given parameters: CLASS, INS, P0, P1, LC, DATA, LE.  A value of -1
367    for LC won't sent this field and the data field; in this case DATA
368    must also be passed as NULL.  The return value is the status word
369    or -1 for an invalid SLOT or other non card related error.  If
370    RETBUF is not NULL, it will receive an allocated buffer with the
371    returned data.  The length of that data will be put into
372    *RETBUFLEN.  The caller is reposnible for releasing the buffer even
373    in case of errors.  */
374 int 
375 apdu_send_le(int slot, int class, int ins, int p0, int p1,
376              int lc, const char *data, int le,
377              unsigned char **retbuf, size_t *retbuflen)
378 {
379   unsigned char result[256+10]; /* 10 extra in case of bugs in the driver. */
380   size_t resultlen = 256;
381   unsigned char apdu[5+256+1];
382   size_t apdulen;
383   int rc, sw;
384
385   if (DBG_CARD_IO)
386     log_debug ("send apdu: c=%02X i=%02X p0=%02X p1=%02X lc=%d le=%d\n",
387                class, ins, p0, p1, lc, le);
388
389   if (lc != -1 && (lc > 255 || lc < 0))
390     return SW_WRONG_LENGTH; 
391   if (le != -1 && (le > 256 || le < 1))
392     return SW_WRONG_LENGTH; 
393   if ((!data && lc != -1) || (data && lc == -1))
394     return -1;
395
396   apdulen = 0;
397   apdu[apdulen++] = class;
398   apdu[apdulen++] = ins;
399   apdu[apdulen++] = p0;
400   apdu[apdulen++] = p1;
401   if (lc != -1)
402     {
403       apdu[apdulen++] = lc;
404       memcpy (apdu+apdulen, data, lc);
405       apdulen += lc;
406     }
407   if (le != -1)
408     apdu[apdulen++] = le; /* Truncation is okay becuase 0 means 256. */
409   assert (sizeof (apdu) >= apdulen);
410   /* As safeguard don't pass any garbage from the stack to the driver. */
411   memset (apdu+apdulen, 0, sizeof (apdu) - apdulen);
412   rc = send_apdu (slot, apdu, apdulen, result, &resultlen);
413   if (rc || resultlen < 2)
414     {
415       log_error ("apdu_send_simple(%d) failed: %s\n",
416                  slot, error_string (slot, rc));
417       return -1;
418     }
419   sw = (result[resultlen-2] << 8) | result[resultlen-1];
420   /* store away the returned data but strip the statusword. */
421   resultlen -= 2;
422   if (DBG_CARD_IO)
423     {
424       log_debug (" response: sw=%04X  datalen=%d\n", sw, resultlen);
425       if ( !retbuf && (sw == SW_SUCCESS || (sw & 0xff00) == SW_MORE_DATA))
426         log_printhex ("     dump: ", result, resultlen);
427     }
428
429   if (sw == SW_SUCCESS)
430     {
431       if (retbuf)
432         {
433           *retbuf = xtrymalloc (resultlen? resultlen : 1);
434           if (!*retbuf)
435             return -1; /* fixme: this is actually out of core. */
436           *retbuflen = resultlen;
437           memcpy (*retbuf, result, resultlen);
438         }
439     }
440   else if ((sw & 0xff00) == SW_MORE_DATA)
441     {
442       unsigned char *p = NULL, *tmp;
443       size_t bufsize = 4096;
444
445       /* It is likely that we need to return much more data, so we
446          start off with a large buffer. */
447       if (retbuf)
448         {
449           *retbuf = p = xtrymalloc (bufsize);
450           if (!*retbuf)
451             return -1; /* fixme: this is actually out of core. */
452           assert (resultlen < bufsize);
453           memcpy (p, result, resultlen);
454           p += resultlen;
455         }
456
457       do
458         {
459           int len = (sw & 0x00ff);
460           
461           log_debug ("apdu_send_simple(%d): %d more bytes available\n",
462                      slot, len);
463           apdulen = 0;
464           apdu[apdulen++] = class;
465           apdu[apdulen++] = 0xC0;
466           apdu[apdulen++] = 0;
467           apdu[apdulen++] = 0;
468           apdu[apdulen++] = 64; /* that is 256 bytes for Le */
469           memset (apdu+apdulen, 0, sizeof (apdu) - apdulen);
470           rc = send_apdu (slot, apdu, apdulen, result, &resultlen);
471           if (rc || resultlen < 2)
472             {
473               log_error ("apdu_send_simple(%d) for get response failed: %s\n",
474                          slot, error_string (slot, rc));
475               return -1;
476             }
477           sw = (result[resultlen-2] << 8) | result[resultlen-1];
478           resultlen -= 2;
479           if (DBG_CARD_IO)
480             {
481               log_debug ("     more: sw=%04X  datalen=%d\n", sw, resultlen);
482               if (!retbuf && (sw==SW_SUCCESS || (sw&0xff00)==SW_MORE_DATA))
483                 log_printhex ("     dump: ", result, resultlen);
484             }
485
486           if ((sw & 0xff00) == SW_MORE_DATA || sw == SW_SUCCESS)
487             {
488               if (retbuf)
489                 {
490                   if (p - *retbuf + resultlen > bufsize)
491                     {
492                       bufsize += resultlen > 4096? resultlen: 4096;
493                       tmp = xtryrealloc (*retbuf, bufsize);
494                       if (!tmp)
495                         return -1; /* fixme: actually this is out of core */
496                       p = tmp + (p - *retbuf);
497                       *retbuf = tmp;
498                     }
499                   memcpy (p, result, resultlen);
500                   p += resultlen;
501                 }
502             }
503           else
504             log_info ("apdu_send_simple(%d) "
505                       "got unexpected status %04X from get response\n",
506                       slot, sw);
507         }
508       while ((sw & 0xff00) == SW_MORE_DATA);
509       
510       if (retbuf)
511         {
512           *retbuflen = p - *retbuf;
513           tmp = xtryrealloc (*retbuf, *retbuflen);
514           if (tmp)
515             *retbuf = tmp;
516         }
517     }
518   if (DBG_CARD_IO && retbuf && sw == SW_SUCCESS)
519     log_printhex ("      dump: ", *retbuf, *retbuflen);
520  
521   return sw;
522 }
523
524 /* Send an APDU to the card in SLOT.  The APDU is created from all
525    given parameters: CLASS, INS, P0, P1, LC, DATA.  A value of -1 for
526    LC won't sent this field and the data field; in this case DATA must
527    also be passed as NULL. The return value is the status word or -1
528    for an invalid SLOT or other non card related error.  If RETBUF is
529    not NULL, it will receive an allocated buffer with the returned
530    data.  The length of that data will be put into *RETBUFLEN.  The
531    caller is reponsible for releasing the buffer even in case of
532    errors.  */
533 int 
534 apdu_send(int slot, int class, int ins, int p0, int p1,
535           int lc, const char *data, unsigned char **retbuf, size_t *retbuflen)
536 {
537   return apdu_send_le (slot, class, ins, p0, p1, lc, data, 256, 
538                        retbuf, retbuflen);
539 }
540
541 /* Send an APDU to the card in SLOT.  The APDU is created from all
542    given parameters: CLASS, INS, P0, P1, LC, DATA.  A value of -1 for
543    LC won't sent this field and the data field; in this case DATA must
544    also be passed as NULL. The return value is the status word or -1
545    for an invalid SLOT or other non card related error.  No data will be
546    returned. */
547 int 
548 apdu_send_simple (int slot, int class, int ins, int p0, int p1,
549                   int lc, const char *data)
550 {
551   return apdu_send (slot, class, ins, p0, p1, lc, data, NULL, NULL);
552 }