* scdaemon.h: Include gpg-error.h and errno.h
[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 "iso7816.h"
30
31 static struct {
32   int tag;
33   int constructed;
34   int get_from;  /* Constructed DO with this DO or 0 for direct access. */
35   int binary;
36   char *desc;
37 } data_objects[] = {
38   { 0x005E, 0,    0, 1, "Login Data" },
39   { 0x5F50, 0,    0, 0, "URL" },
40   { 0x0065, 1,    0, 1, "Cardholder Related Data"},
41   { 0x005B, 0, 0x65, 0, "Name" },
42   { 0x5F2D, 0, 0x65, 0, "Language preferences" },
43   { 0x5F35, 0, 0x65, 0, "Sex" },
44   { 0x006E, 1,    0, 1, "Application Related Data" },
45   { 0x004F, 0, 0x6E, 1, "AID" },
46   { 0x0073, 1,    0, 1, "Discretionary Data Objects" },
47   { 0x0047, 0, 0x6E, 1, "Card Capabilities" },
48   { 0x00C0, 0, 0x6E, 1, "Extended Card Capabilities" },
49   { 0x00C1, 0, 0x6E, 1, "Algorithm Attributes Signature" },
50   { 0x00C2, 0, 0x6E, 1, "Algorithm Attributes Decryption" },
51   { 0x00C3, 0, 0x6E, 1, "Algorithm Attributes Authentication" },
52   { 0x00C4, 0, 0x6E, 1, "CHV Status Bytes" },
53   { 0x00C5, 0, 0x6E, 1, "Fingerprints" },
54   { 0x00C6, 0, 0x6E, 1, "CA Fingerprints" },
55   { 0x007A, 1,    0, 1, "Security Support Template" },
56   { 0x0093, 0, 0x7A, 1, "Digital Signature Counter" },
57   { 0 }
58 };
59
60
61 /* Locate a TLV encoded data object in BUFFER of LENGTH and
62    return a pointer to value as well as its length in NBYTES.  Return
63    NULL if it was not found.  Note, that the function does not check
64    whether the value fits into the provided buffer. 
65
66    FIXME: Move this to an extra file, it is mostly duplicated from card.c.
67 */
68 static const unsigned char *
69 find_tlv (const unsigned char *buffer, size_t length,
70           int tag, size_t *nbytes, int nestlevel)
71 {
72   const unsigned char *s = buffer;
73   size_t n = length;
74   size_t len;
75   int this_tag;
76   int composite;
77     
78   for (;;)
79     {
80       buffer = s;
81       if (n < 2)
82         return NULL; /* buffer definitely too short for tag and length. */
83       composite = !!(*s & 0x20);
84       if ((*s & 0x1f) == 0x1f)
85         { /* more tag bytes to follow */
86           s++;
87           n--;
88           if (n < 2)
89             return NULL; /* buffer definitely too short for tag and length. */
90           if ((*s & 0x1f) == 0x1f)
91             return NULL; /* We support only up to 2 bytes. */
92           this_tag = (s[-1] << 8) | (s[0] & 0x7f);
93         }
94       else
95         this_tag = s[0];
96       len = s[1];
97       s += 2; n -= 2;
98       if (len == 255)
99         {
100           if (n < 2)
101             return NULL; /* we expected 2 more bytes with the length. */
102           len = (s[0] << 8) | s[1];
103           s += 2; n -= 2;
104         }
105       if (composite && nestlevel < 100)
106         { /* Dive into this composite DO after checking for too deep
107              nesting. */
108           const unsigned char *tmp_s;
109           size_t tmp_len;
110           
111           tmp_s = find_tlv (s, len, tag, &tmp_len, nestlevel+1);
112           if (tmp_s)
113             {
114               *nbytes = tmp_len;
115               return tmp_s;
116             }
117         }
118
119       if (this_tag == tag)
120         {
121           *nbytes = len;
122           return s;
123         }
124       if (len > n)
125         return NULL; /* buffer too short to skip to the next tag. */
126       s += len; n -= len;
127     }
128 }
129
130
131
132 static void
133 dump_one_do (int slot, int tag)
134 {
135   int rc, i;
136   unsigned char *buffer;
137   size_t buflen;
138   const char *desc;
139   int binary;
140   const unsigned char *value;
141   size_t valuelen;
142
143   for (i=0; data_objects[i].tag && data_objects[i].tag != tag; i++)
144     ;
145   desc = data_objects[i].tag? data_objects[i].desc : "?";
146   binary = data_objects[i].tag? data_objects[i].binary : 1;
147
148   value = NULL;
149   rc = -1;
150   if (data_objects[i].tag && data_objects[i].get_from)
151     {
152       rc = iso7816_get_data (slot, data_objects[i].get_from,
153                              &buffer, &buflen);
154       if (!rc)
155         {
156           value = find_tlv (buffer, buflen, tag, &valuelen, 0);
157           if (!value)
158             ; /* not found */
159           else if (valuelen > buflen - (value - buffer))
160             {
161               log_error ("warning: constructed DO too short\n");
162               value = NULL;
163               xfree (buffer); buffer = NULL;
164             }
165         }
166     }
167
168   if (!value) /* Not in a constructed DO, try simple. */
169     {
170       rc = iso7816_get_data (slot, tag, &buffer, &buflen);
171       if (!rc)
172         {
173           value = buffer;
174           valuelen = buflen;
175         }
176     }
177   if (rc == 0x6a88)
178     log_info ("DO `%s' not available\n", desc);
179   else if (rc) 
180     log_info ("DO `%s' not available (rc=%04X)\n", desc, rc);
181   else
182     {
183       if (binary)
184         {
185           log_info ("DO `%s': ", desc);
186           log_printhex ("", value, valuelen);
187         }
188       else
189         log_info ("DO `%s': `%.*s'\n",
190                   desc, (int)valuelen, value); /* FIXME: sanitize */
191       xfree (buffer);
192     }
193 }
194
195
196 static void
197 dump_all_do (int slot)
198 {
199   int rc, i, j;
200   unsigned char *buffer;
201   size_t buflen;
202   
203   for (i=0; data_objects[i].tag; i++)
204     {
205       if (data_objects[i].get_from)
206         continue;
207
208       rc = iso7816_get_data (slot, data_objects[i].tag, &buffer, &buflen);
209       if (rc == 0x6a88)
210         ;
211       else if (rc) 
212         log_info ("DO `%s' not available (rc=%04X)\n",
213                   data_objects[i].desc, rc);
214       else
215         {
216           if (data_objects[i].binary)
217             {
218               log_info ("DO `%s': ", data_objects[i].desc);
219               log_printhex ("", buffer, buflen);
220             }
221           else
222             log_info ("DO `%s': `%.*s'\n",
223                       data_objects[i].desc,
224                       (int)buflen, buffer); /* FIXME: sanitize */
225         }
226
227       if (data_objects[i].constructed)
228         {
229           for (j=0; data_objects[j].tag; j++)
230             {
231               const unsigned char *value;
232               size_t valuelen;
233
234               if (j==i || data_objects[i].tag != data_objects[j].get_from)
235                 continue;
236               value = find_tlv (buffer, buflen,
237                                 data_objects[j].tag, &valuelen, 0);
238               if (!value)
239                 ; /* not found */
240               else if (valuelen > buflen - (value - buffer))
241                 log_error ("warning: constructed DO too short\n");
242               else
243                 {
244                   if (data_objects[j].binary)
245                     {
246                       log_info ("DO `%s': ", data_objects[j].desc);
247                       log_printhex ("", value, valuelen);
248                     }
249                   else
250                     log_info ("DO `%s': `%.*s'\n",
251                               data_objects[j].desc,
252                               (int)valuelen, value); /* FIXME: sanitize */
253                 }
254             }
255         }
256       xfree (buffer); buffer = NULL;
257     }
258 }
259
260
261 static int 
262 store_fpr (int slot, int keynumber, u32 timestamp,
263            const unsigned char *m, size_t mlen,
264            const unsigned char *e, size_t elen)
265 {
266   unsigned int n;
267   unsigned char *buffer, *p;
268   unsigned char fpr[20];
269   int rc;
270   
271   n = 6 + 2 + mlen + 2 + elen;
272   p = buffer = xtrymalloc (3 + n);
273   if (!buffer)
274     return out_of_core ();
275   
276   *p++ = 0x99;     /* ctb */
277   *p++ = n >> 8;   /* 2 byte length header */
278   *p++ = n;
279   *p++ = 4;        /* key packet version */
280   *p++ = timestamp >> 24;
281   *p++ = timestamp >> 16;
282   *p++ = timestamp >>  8;
283   *p++ = timestamp;
284   *p++ = 1; /* RSA */
285   *p++ = mlen >> 8;
286   *p++ = mlen;
287   memcpy (p, m, mlen); p += mlen;
288   *p++ = elen >> 8;
289   *p++ = elen;
290   memcpy (p, e, elen); p += elen;
291     
292   gcry_md_hash_buffer (GCRY_MD_SHA1, fpr, buffer, n+3);
293   xfree (buffer);
294
295   rc = iso7816_put_data (slot, 0xC6 + keynumber, fpr, 20);
296   if (rc)
297     log_error ("failed to store the fingerprint: rc=%04X\n", rc);
298
299   return rc;
300 }
301
302
303
304 /* Generate a new key on the card and store the fingerprint in the
305    corresponding DO.  A KEYNUMBER of 0 creates the digital signature
306    key, 1 the encryption key and 2 the authentication key.  If the key
307    already exists an error is returned unless FORCE has been set to
308    true.  Note, that the function does not return the public key; this
309    has to be done using openpgp_readkey(). */
310 int
311 openpgp_genkey (int slot, int keynumber, int force)
312 {
313   int rc;
314   int i;
315   const unsigned char *fpr;
316   const unsigned char *keydata, *m, *e;
317   unsigned char *buffer;
318   size_t buflen, keydatalen, n, mlen, elen;
319   time_t created_at;
320   
321   if (keynumber < 0 || keynumber > 2)
322     return -1; /* invalid value */
323
324   rc = iso7816_get_data (slot, 0x006E, &buffer, &buflen);
325   if (rc)
326     {
327       log_error ("error reading application data\n");
328       return -1;
329     }
330   fpr = find_tlv (buffer, buflen, 0x00C5, &n, 0);
331   if (!fpr || n != 60)
332     {
333       log_error ("error reading fingerprint DO\n");
334       goto leave;
335     }
336   fpr += 20*keynumber;
337   for (i=0; i < 20 && !fpr[i]; i++)
338     ;
339   if (i!=20 && !force)
340     {
341       log_error ("key already exists\n");
342       goto leave;
343     }
344   else if (i!=20)
345     log_info ("existing key will be replaced\n");
346   else
347     log_info ("generating new key\n");
348
349
350   rc = iso7816_verify (slot, 0x83, "12345678", 8);
351   if (rc)
352     {
353       log_error ("verify CHV3 failed: rc=%04X\n", rc);
354       goto leave;
355     }
356
357   xfree (buffer); buffer = NULL;
358   rc = iso7816_generate_keypair (slot, 
359                                  keynumber == 0? "\xB6" :
360                                  keynumber == 1? "\xB8" : "\xA4",
361                                  2,
362                                  &buffer, &buflen);
363   if (rc)
364     {
365       log_error ("generating key failed\n");
366       goto leave;
367     }
368   keydata = find_tlv (buffer, buflen, 0x7F49, &keydatalen, 0);
369   if (!keydata)
370     {
371       log_error ("response does not contain the public key data\n");
372       goto leave;
373     }
374  
375
376   m = find_tlv (keydata, keydatalen, 0x0081, &mlen, 0);
377   if (!m)
378     {
379       log_error ("response does not contain the RSA modulus\n");
380       goto leave;
381     }
382   log_printhex ("RSA n:", m, mlen);
383   e = find_tlv (keydata, keydatalen, 0x0082, &elen, 0);
384   if (!e)
385     {
386       log_error ("response does not contain the RSA public exponent\n");
387       goto leave;
388     }
389   log_printhex ("RSA e:", e, elen);
390   created_at = gnupg_get_time ();
391   rc = store_fpr (slot, keynumber, (u32)created_at, m, mlen, e, elen);
392
393
394  leave:
395   xfree (buffer);
396   return rc;
397 }
398
399
400 /* Select the OpenPGP application on the card in SLOT.  This function
401    must be used to before any other OpenPGP application functions. */
402 int
403 app_select_openpgp (int slot)
404 {
405   static char const aid[] = { 0xD2, 0x76, 0x00, 0x01, 0x24, 0x01 };
406   int rc;
407   unsigned char *buffer;
408   size_t buflen;
409   
410   rc = iso7816_select_application (slot, aid, sizeof aid);
411   if (!rc)
412     {
413       /* fixme: get the full AID and check that the version is okay
414          with us. */
415       rc = iso7816_get_data (slot, 0x004F, &buffer, &buflen);
416       if (rc)
417         goto leave;
418       if (opt.verbose)
419       log_info ("got AID: ");
420       log_printhex ("", buffer, buflen);
421       xfree (buffer);
422
423       dump_all_do (slot);
424
425 /*        rc = iso7816_verify (slot, 0x83, "12345678", 8); */
426 /*        if (rc) */
427 /*          log_error ("verify CHV3 failed: rc=%04X\n", rc); */
428       
429
430 /*        rc = iso7816_put_data (slot, 0x005B, "Joe Hacker", 10); */
431 /*        if (rc) */
432 /*          log_error ("failed to set `Name': rc=%04X\n", rc); */
433 /*        else */
434 /*          dump_one_do (slot, 0x005B); */
435       
436       /* fixme: associate the internal state with the slot */
437     }
438
439 leave:
440   return rc;
441 }
442