Key generation and signing using the OpenPGP card does rudimentary work.
[gnupg.git] / scd / app-openpgp.c
1 /* app-openpgp.c - The OpenPGP card application.
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
28 #include "scdaemon.h"
29 #include "app-common.h"
30 #include "iso7816.h"
31
32
33
34 static struct {
35   int tag;
36   int constructed;
37   int get_from;  /* Constructed DO with this DO or 0 for direct access. */
38   int binary;
39   char *desc;
40 } data_objects[] = {
41   { 0x005E, 0,    0, 1, "Login Data" },
42   { 0x5F50, 0,    0, 0, "URL" },
43   { 0x0065, 1,    0, 1, "Cardholder Related Data"},
44   { 0x005B, 0, 0x65, 0, "Name" },
45   { 0x5F2D, 0, 0x65, 0, "Language preferences" },
46   { 0x5F35, 0, 0x65, 0, "Sex" },
47   { 0x006E, 1,    0, 1, "Application Related Data" },
48   { 0x004F, 0, 0x6E, 1, "AID" },
49   { 0x0073, 1,    0, 1, "Discretionary Data Objects" },
50   { 0x0047, 0, 0x6E, 1, "Card Capabilities" },
51   { 0x00C0, 0, 0x6E, 1, "Extended Card Capabilities" },
52   { 0x00C1, 0, 0x6E, 1, "Algorithm Attributes Signature" },
53   { 0x00C2, 0, 0x6E, 1, "Algorithm Attributes Decryption" },
54   { 0x00C3, 0, 0x6E, 1, "Algorithm Attributes Authentication" },
55   { 0x00C4, 0, 0x6E, 1, "CHV Status Bytes" },
56   { 0x00C5, 0, 0x6E, 1, "Fingerprints" },
57   { 0x00C6, 0, 0x6E, 1, "CA Fingerprints" },
58   { 0x007A, 1,    0, 1, "Security Support Template" },
59   { 0x0093, 0, 0x7A, 1, "Digital Signature Counter" },
60   { 0 }
61 };
62
63
64 /* Locate a TLV encoded data object in BUFFER of LENGTH and
65    return a pointer to value as well as its length in NBYTES.  Return
66    NULL if it was not found.  Note, that the function does not check
67    whether the value fits into the provided buffer. 
68
69    FIXME: Move this to an extra file, it is mostly duplicated from card.c.
70 */
71 static const unsigned char *
72 find_tlv (const unsigned char *buffer, size_t length,
73           int tag, size_t *nbytes, int nestlevel)
74 {
75   const unsigned char *s = buffer;
76   size_t n = length;
77   size_t len;
78   int this_tag;
79   int composite;
80     
81   for (;;)
82     {
83       buffer = s;
84       if (n < 2)
85         return NULL; /* buffer definitely too short for tag and length. */
86       if (!*s || *s == 0xff)
87         { /* Skip optional filler between TLV objects. */
88           s++;
89           n--;
90           continue;
91         }
92       composite = !!(*s & 0x20);
93       if ((*s & 0x1f) == 0x1f)
94         { /* more tag bytes to follow */
95           s++;
96           n--;
97           if (n < 2)
98             return NULL; /* buffer definitely too short for tag and length. */
99           if ((*s & 0x1f) == 0x1f)
100             return NULL; /* We support only up to 2 bytes. */
101           this_tag = (s[-1] << 8) | (s[0] & 0x7f);
102         }
103       else
104         this_tag = s[0];
105       len = s[1];
106       s += 2; n -= 2;
107       if (len < 0x80)
108         ;
109       else if (len == 0x81)
110         { /* One byte length follows. */
111           if (!n)
112             return NULL; /* we expected 1 more bytes with the length. */
113           len = s[0];
114           s++; n--;
115         }
116       else if (len == 0x82)
117         { /* Two byte length follows. */
118           if (n < 2)
119             return NULL; /* we expected 2 more bytes with the length. */
120           len = (s[0] << 8) | s[1];
121           s += 2; n -= 2;
122         }
123       else
124         return NULL; /* APDU limit is 65535, thus it does not make
125                         sense to assume longer length fields. */
126
127       if (composite && nestlevel < 100)
128         { /* Dive into this composite DO after checking for too deep
129              nesting. */
130           const unsigned char *tmp_s;
131           size_t tmp_len;
132           
133           tmp_s = find_tlv (s, len, tag, &tmp_len, nestlevel+1);
134           if (tmp_s)
135             {
136               *nbytes = tmp_len;
137               return tmp_s;
138             }
139         }
140
141       if (this_tag == tag)
142         {
143           *nbytes = len;
144           return s;
145         }
146       if (len > n)
147         return NULL; /* buffer too short to skip to the next tag. */
148       s += len; n -= len;
149     }
150 }
151
152
153 /* Get the DO identified by TAG from the card in SLOT and return a
154    buffer with its content in RESULT and NBYTES.  The return value is
155    NULL if not found or a pointer which must be used to release the
156    buffer holding value. */
157 static void *
158 get_one_do (int slot, int tag, unsigned char **result, size_t *nbytes)
159 {
160   int rc, i;
161   unsigned char *buffer;
162   size_t buflen;
163   unsigned char *value;
164   size_t valuelen;
165
166   *result = NULL;
167   *nbytes = 0;
168   for (i=0; data_objects[i].tag && data_objects[i].tag != tag; i++)
169     ;
170
171   value = NULL;
172   rc = -1;
173   if (data_objects[i].tag && data_objects[i].get_from)
174     {
175       rc = iso7816_get_data (slot, data_objects[i].get_from,
176                              &buffer, &buflen);
177       if (!rc)
178         {
179           value = find_tlv (buffer, buflen, tag, &valuelen, 0);
180           if (!value)
181             ; /* not found */
182           else if (valuelen > buflen - (value - buffer))
183             {
184               log_error ("warning: constructed DO too short\n");
185               value = NULL;
186               xfree (buffer); buffer = NULL;
187             }
188         }
189     }
190
191   if (!value) /* Not in a constructed DO, try simple. */
192     {
193       rc = iso7816_get_data (slot, tag, &buffer, &buflen);
194       if (!rc)
195         {
196           value = buffer;
197           valuelen = buflen;
198         }
199     }
200
201   if (!rc)
202     {
203       *nbytes = valuelen;
204       *result = value;
205       return buffer;
206     }
207   return NULL;
208 }
209
210 #if 0 /* not used */
211 static void
212 dump_one_do (int slot, int tag)
213 {
214   int rc, i;
215   unsigned char *buffer;
216   size_t buflen;
217   const char *desc;
218   int binary;
219   const unsigned char *value;
220   size_t valuelen;
221
222   for (i=0; data_objects[i].tag && data_objects[i].tag != tag; i++)
223     ;
224   desc = data_objects[i].tag? data_objects[i].desc : "?";
225   binary = data_objects[i].tag? data_objects[i].binary : 1;
226
227   value = NULL;
228   rc = -1;
229   if (data_objects[i].tag && data_objects[i].get_from)
230     {
231       rc = iso7816_get_data (slot, data_objects[i].get_from,
232                              &buffer, &buflen);
233       if (!rc)
234         {
235           value = find_tlv (buffer, buflen, tag, &valuelen, 0);
236           if (!value)
237             ; /* not found */
238           else if (valuelen > buflen - (value - buffer))
239             {
240               log_error ("warning: constructed DO too short\n");
241               value = NULL;
242               xfree (buffer); buffer = NULL;
243             }
244         }
245     }
246
247   if (!value) /* Not in a constructed DO, try simple. */
248     {
249       rc = iso7816_get_data (slot, tag, &buffer, &buflen);
250       if (!rc)
251         {
252           value = buffer;
253           valuelen = buflen;
254         }
255     }
256   if (rc == 0x6a88)
257     log_info ("DO `%s' not available\n", desc);
258   else if (rc) 
259     log_info ("DO `%s' not available (rc=%04X)\n", desc, rc);
260   else
261     {
262       if (binary)
263         {
264           log_info ("DO `%s': ", desc);
265           log_printhex ("", value, valuelen);
266         }
267       else
268         log_info ("DO `%s': `%.*s'\n",
269                   desc, (int)valuelen, value); /* FIXME: sanitize */
270       xfree (buffer);
271     }
272 }
273 #endif /*not used*/
274
275
276 static void
277 dump_all_do (int slot)
278 {
279   int rc, i, j;
280   unsigned char *buffer;
281   size_t buflen;
282   
283   for (i=0; data_objects[i].tag; i++)
284     {
285       if (data_objects[i].get_from)
286         continue;
287
288       rc = iso7816_get_data (slot, data_objects[i].tag, &buffer, &buflen);
289       if (rc == 0x6a88)
290         ;
291       else if (rc) 
292         log_info ("DO `%s' not available (rc=%04X)\n",
293                   data_objects[i].desc, rc);
294       else
295         {
296           if (data_objects[i].binary)
297             {
298               log_info ("DO `%s': ", data_objects[i].desc);
299               log_printhex ("", buffer, buflen);
300             }
301           else
302             log_info ("DO `%s': `%.*s'\n",
303                       data_objects[i].desc,
304                       (int)buflen, buffer); /* FIXME: sanitize */
305         }
306
307       if (data_objects[i].constructed)
308         {
309           for (j=0; data_objects[j].tag; j++)
310             {
311               const unsigned char *value;
312               size_t valuelen;
313
314               if (j==i || data_objects[i].tag != data_objects[j].get_from)
315                 continue;
316               value = find_tlv (buffer, buflen,
317                                 data_objects[j].tag, &valuelen, 0);
318               if (!value)
319                 ; /* not found */
320               else if (valuelen > buflen - (value - buffer))
321                 log_error ("warning: constructed DO too short\n");
322               else
323                 {
324                   if (data_objects[j].binary)
325                     {
326                       log_info ("DO `%s': ", data_objects[j].desc);
327                       log_printhex ("", value, valuelen);
328                     }
329                   else
330                     log_info ("DO `%s': `%.*s'\n",
331                               data_objects[j].desc,
332                               (int)valuelen, value); /* FIXME: sanitize */
333                 }
334             }
335         }
336       xfree (buffer); buffer = NULL;
337     }
338 }
339
340 /* Note, that FPR must be at least 20 bytes. */
341 static int 
342 store_fpr (int slot, int keynumber, u32 timestamp,
343            const unsigned char *m, size_t mlen,
344            const unsigned char *e, size_t elen, 
345            unsigned char *fpr)
346 {
347   unsigned int n;
348   unsigned char *buffer, *p;
349   int rc;
350   
351   n = 6 + 2 + mlen + 2 + elen;
352   p = buffer = xtrymalloc (3 + n);
353   if (!buffer)
354     return out_of_core ();
355   
356   *p++ = 0x99;     /* ctb */
357   *p++ = n >> 8;   /* 2 byte length header */
358   *p++ = n;
359   *p++ = 4;        /* key packet version */
360   *p++ = timestamp >> 24;
361   *p++ = timestamp >> 16;
362   *p++ = timestamp >>  8;
363   *p++ = timestamp;
364   *p++ = 1; /* RSA */
365   *p++ = mlen >> 8;
366   *p++ = mlen;
367   memcpy (p, m, mlen); p += mlen;
368   *p++ = elen >> 8;
369   *p++ = elen;
370   memcpy (p, e, elen); p += elen;
371     
372   gcry_md_hash_buffer (GCRY_MD_SHA1, fpr, buffer, n+3);
373   xfree (buffer);
374
375   rc = iso7816_put_data (slot, 0xC6 + keynumber, fpr, 20);
376   if (rc)
377     log_error ("failed to store the fingerprint: rc=%04X\n", rc);
378
379   return rc;
380 }
381
382        
383 static void
384 send_fpr_if_not_null (CTRL ctrl, const char *keyword,
385                       int number, const unsigned char *fpr)
386 {                      
387   int i;
388   char buf[41];
389   char numbuf[25];
390
391   for (i=0; i < 20 && !fpr[i]; i++)
392     ;
393   if (i==20)
394     return; /* All zero. */
395   for (i=0; i< 20; i++)
396     sprintf (buf+2*i, "%02X", fpr[i]);
397   if (number == -1)
398     *numbuf = 0; /* Don't print the key number */
399   else
400     sprintf (numbuf, "%d", number);
401   send_status_info (ctrl, keyword,
402                     numbuf, (size_t)strlen(numbuf),
403                     buf, (size_t)strlen (buf), NULL, 0);
404 }
405
406 static void
407 send_key_data (CTRL ctrl, const char *name, 
408                const unsigned char *a, size_t alen)
409 {
410   char *p, *buf = xmalloc (alen*2+1);
411   
412   for (p=buf; alen; a++, alen--, p += 2)
413     sprintf (p, "%02X", *a);
414
415   send_status_info (ctrl, "KEY-DATA",
416                     name, (size_t)strlen(name), 
417                     buf, (size_t)strlen (buf),
418                     NULL, 0);
419   xfree (buf);
420 }
421
422
423
424 static int
425 do_learn_status (APP app, CTRL ctrl)
426 {
427   void *relptr;
428   unsigned char *value;
429   size_t valuelen;
430   int i;
431
432   relptr = get_one_do (app->slot, 0x005B, &value, &valuelen);
433   if (relptr)
434     {
435       send_status_info (ctrl, "DISP-NAME", value, valuelen, NULL, 0);
436       xfree (relptr);
437     }
438   relptr = get_one_do (app->slot, 0x5FF0, &value, &valuelen);
439   if (relptr)
440     {
441       send_status_info (ctrl, "PUBKEY-URL", value, valuelen, NULL, 0);
442       xfree (relptr);
443     }
444
445   relptr = get_one_do (app->slot, 0x00C5, &value, &valuelen);
446   if (relptr && valuelen >= 60)
447     {
448       for (i=0; i < 3; i++)
449         send_fpr_if_not_null (ctrl, "KEY-FPR", i+1, value+i*20);
450     }
451   xfree (relptr);
452   relptr = get_one_do (app->slot, 0x00C6, &value, &valuelen);
453   if (relptr && valuelen >= 60)
454     {
455       for (i=0; i < 3; i++)
456         send_fpr_if_not_null (ctrl, "CA-FPR", i+1, value+i*20);
457     }
458   xfree (relptr);
459   return 0;
460 }
461
462
463 /* Handle the SETATTR operation. All arguments are already basically
464    checked. */
465 static int 
466 do_setattr (APP app, const char *name,
467             int (*pincb)(void*, const char *, char **),
468             void *pincb_arg,
469             const unsigned char *value, size_t valuelen)
470 {
471   gpg_error_t rc;
472
473   log_debug ("app_openpgp#setattr `%s' value of length %u\n",
474              name, (unsigned int)valuelen); /* fixme: name should be
475                                                sanitized. */
476
477   if (!app->did_chv3)
478     {
479       char *pinvalue;
480
481 /*        rc = pincb (pincb_arg, "Please enter the card's admin PIN (CHV3)", */
482 /*                    &pinvalue); */
483       pinvalue = xstrdup ("12345678");
484       rc = 0;
485       if (rc)
486         {
487           log_info ("PIN callback returned error: %s\n", gpg_strerror (rc));
488           return rc;
489         }
490
491       rc = iso7816_verify (app->slot, 0x83, pinvalue, strlen (pinvalue));
492       xfree (pinvalue);
493       if (rc)
494         {
495           log_error ("verify CHV3 failed\n");
496           rc = gpg_error (GPG_ERR_GENERAL);
497           return rc;
498         }
499       app->did_chv3 = 1;
500     }
501
502   log_debug ("setting `%s' to `%.*s'\n", name, (int)valuelen, value);
503   if (!strcmp (name, "DISP-NAME"))
504     {
505       rc = iso7816_put_data (app->slot, 0x005B, value, valuelen);
506       if (rc)
507         {
508           /* FIXME: If this fails we should *once* try again after
509           doing a verify command, so that in case of a problem with
510           tracking the verify operation we have a fallback. */
511           /* FIXME: change this when iso7816 returns correct error
512           codes. */
513           log_error ("failed to set `Name'\n");
514           rc = gpg_error (GPG_ERR_GENERAL);
515         }
516     }
517   else
518     rc = gpg_error (GPG_ERR_INV_NAME); 
519
520   return rc;
521 }
522
523
524 /* Handle the GENKEY command. */
525 static int 
526 do_genkey (APP app, CTRL ctrl,  const char *keynostr, unsigned int flags,
527           int (*pincb)(void*, const char *, char **),
528           void *pincb_arg)
529 {
530   int rc;
531   int i;
532   char numbuf[30];
533   unsigned char fprbuf[20];
534   const unsigned char *fpr;
535   const unsigned char *keydata, *m, *e;
536   unsigned char *buffer;
537   size_t buflen, keydatalen, n, mlen, elen;
538   time_t created_at;
539   int keyno = atoi (keynostr);
540   int force = (flags & 1);
541
542   if (keyno < 1 || keyno > 3)
543     return gpg_error (GPG_ERR_INV_ID);
544   keyno--;
545
546   rc = iso7816_get_data (app->slot, 0x006E, &buffer, &buflen);
547   if (rc)
548     {
549       log_error ("error reading application data\n");
550       return gpg_error (GPG_ERR_GENERAL);
551     }
552   fpr = find_tlv (buffer, buflen, 0x00C5, &n, 0);
553   if (!fpr || n != 60)
554     {
555       rc = gpg_error (GPG_ERR_GENERAL);
556       log_error ("error reading fingerprint DO\n");
557       goto leave;
558     }
559   fpr += 20*keyno;
560   for (i=0; i < 20 && !fpr[i]; i++)
561     ;
562   if (i!=20 && !force)
563     {
564       rc = gpg_error (GPG_ERR_EEXIST);
565       log_error ("key already exists\n");
566       goto leave;
567     }
568   else if (i!=20)
569     log_info ("existing key will be replaced\n");
570   else
571     log_info ("generating new key\n");
572
573   rc = iso7816_verify (app->slot, 0x83, "12345678", 8);
574   if (rc)
575     {
576       log_error ("verify CHV3 failed: rc=%04X\n", rc);
577       goto leave;
578     }
579
580   xfree (buffer); buffer = NULL;
581   rc = iso7816_generate_keypair (app->slot, 
582                                  keyno == 0? "\xB6" :
583                                  keyno == 1? "\xB8" : "\xA4",
584                                  2,
585                                  &buffer, &buflen);
586   if (rc)
587     {
588       rc = gpg_error (GPG_ERR_CARD);
589       log_error ("generating key failed\n");
590       goto leave;
591     }
592   keydata = find_tlv (buffer, buflen, 0x7F49, &keydatalen, 0);
593   if (!keydata)
594     {
595       log_error ("response does not contain the public key data\n");
596       goto leave;
597     }
598  
599   m = find_tlv (keydata, keydatalen, 0x0081, &mlen, 0);
600   if (!m)
601     {
602       log_error ("response does not contain the RSA modulus\n");
603       goto leave;
604     }
605   log_printhex ("RSA n:", m, mlen);
606   send_key_data (ctrl, "n", m, mlen);
607
608   e = find_tlv (keydata, keydatalen, 0x0082, &elen, 0);
609   if (!e)
610     {
611       log_error ("response does not contain the RSA public exponent\n");
612       goto leave;
613     }
614   log_printhex ("RSA e:", e, elen);
615   send_key_data (ctrl, "e", e, elen);
616
617   created_at = gnupg_get_time ();
618   sprintf (numbuf, "%lu", (unsigned long)created_at);
619   send_status_info (ctrl, "KEY-CREATED-AT",
620                     numbuf, (size_t)strlen(numbuf), NULL, 0);
621
622   rc = store_fpr (app->slot, keyno, (u32)created_at,
623                   m, mlen, e, elen, fprbuf);
624   if (rc)
625     goto leave;
626   send_fpr_if_not_null (ctrl, "KEY-FPR", -1, fprbuf);
627
628
629  leave:
630   xfree (buffer);
631   return rc;
632 }
633
634
635 /* Comopute a digital signature on INDATA which is expected to be the
636    raw message digest. */
637 static int 
638 do_sign (APP app, const char *keyidstr, int hashalgo,
639          int (*pincb)(void*, const char *, char **),
640          void *pincb_arg,
641          const void *indata, size_t indatalen,
642          void **outdata, size_t *outdatalen )
643 {
644   static unsigned char sha1_prefix[15] = /* Object ID is 1.3.14.3.2.26 */
645   { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
646     0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 };
647   static unsigned char rmd160_prefix[15] = /* Object ID is 1.3.36.3.2.1 */
648   { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03,
649     0x02, 0x01, 0x05, 0x00, 0x04, 0x14 };
650   int rc;
651   unsigned char data[35];
652
653   /* We ignore KEYIDSTR, because the OpenPGP application has only one
654      signing key and no way to specify a different one. */
655   
656   if (indatalen != 20)
657     return gpg_error (GPG_ERR_INV_VALUE);
658   if (hashalgo == GCRY_MD_SHA1)
659     memcpy (data, sha1_prefix, 15);
660   else if (hashalgo == GCRY_MD_RMD160)
661     memcpy (data, rmd160_prefix, 15);
662   else 
663     return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
664   memcpy (data+15, indata, indatalen);
665
666
667   if (!app->did_chv1)
668     {
669       char *pinvalue;
670
671 /*        rc = pincb (pincb_arg, "signature PIN", &pinvalue); */
672       pinvalue = xstrdup ("123456");
673       rc = 0;
674       if (rc)
675         {
676           log_info ("PIN callback returned error: %s\n", gpg_strerror (rc));
677           return rc;
678         }
679
680       rc = iso7816_verify (app->slot, 0x81, pinvalue, strlen (pinvalue));
681       xfree (pinvalue);
682       if (rc)
683         {
684           log_error ("verify CHV1 failed\n");
685           rc = gpg_error (GPG_ERR_GENERAL);
686           return rc;
687         }
688       app->did_chv1 = 1;
689     }
690
691   rc = iso7816_compute_ds (app->slot, data, 35, outdata, outdatalen);
692
693   return rc;
694 }
695
696
697 /* Select the OpenPGP application on the card in SLOT.  This function
698    must be used before any other OpenPGP application functions. */
699 int
700 app_select_openpgp (APP app, unsigned char **sn, size_t *snlen)
701 {
702   static char const aid[] = { 0xD2, 0x76, 0x00, 0x01, 0x24, 0x01 };
703   int slot = app->slot;
704   int rc;
705   unsigned char *buffer;
706   size_t buflen;
707   
708   rc = iso7816_select_application (slot, aid, sizeof aid);
709   if (!rc)
710     {
711       /* fixme: get the full AID and check that the version is okay
712          with us. */
713       rc = iso7816_get_data (slot, 0x004F, &buffer, &buflen);
714       if (rc)
715         goto leave;
716       if (opt.verbose)
717         {
718           log_info ("got AID: ");
719           log_printhex ("", buffer, buflen);
720         }
721
722       if (sn)
723         {
724           *sn = buffer;
725           *snlen = buflen;
726         }
727       else
728         xfree (buffer);
729
730       dump_all_do (slot);
731
732       app->fnc.learn_status = do_learn_status;
733       app->fnc.setattr = do_setattr;
734       app->fnc.genkey = do_genkey;
735       app->fnc.sign = do_sign;
736    }
737
738 leave:
739   return rc;
740 }
741
742
743
744