af2eed4651be646b09042d9a3b80560374644fd5
[gnupg.git] / scd / app-p15.c
1 /* app-p15.c - The pkcs#15 card application.
2  *      Copyright (C) 2004 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 <assert.h>
27 #include <time.h>
28
29 #include "scdaemon.h"
30
31 #include "iso7816.h"
32 #include "app-common.h"
33 #include "tlv.h"
34
35
36 /* Context local to this application. */
37 struct app_local_s 
38 {
39   unsigned short home_df;  /* The home DF. Note, that we don't yet
40                               support a multilevel hierachy.  Thus we
41                               assume this is directly below the MF.  */
42   struct
43   {
44     unsigned short private_keys;
45     unsigned short public_keys;
46     unsigned short trusted_public_keys;
47     unsigned short secret_keys;
48     unsigned short certificates;
49     unsigned short trusted_certificates;
50     unsigned short useful_certificates;
51     unsigned short data_objects;
52     unsigned short auth_objects;
53   } odf;  
54
55
56 };
57
58
59
60
61 /* Do a select and a read for the file with EFID.  EFID is a
62    desctription of the EF to be used with error messages.  On success
63    BUFFER and BUFLEN contain the entire content of the EF.  The caller
64    must free BUFFER but only on success. */
65 static gpg_error_t 
66 select_and_read_binary (int slot, unsigned short efid, const char *efid_desc,
67                         unsigned char **buffer, size_t *buflen)
68 {
69   gpg_error_t err;
70
71   err = iso7816_select_file (slot, efid, 0, NULL, NULL);
72   if (err)
73     {
74       log_error ("error selecting %s (0x%04X): %s\n",
75                  efid_desc, efid, gpg_strerror (err));
76       return err;
77     }
78   err = iso7816_read_binary (slot, 0, 0, buffer, buflen);
79   if (err)
80     {
81       log_error ("error reading %s (0x%04X): %s\n",
82                  efid_desc, efid, gpg_strerror (err));
83       return err;
84     }
85   return 0;
86 }
87
88
89
90
91 /* Read and parse the Object Directory File and store away the
92    pointers.
93
94    Example of such a file:
95
96    A0 06 30 04 04 02 60 34  = Private Keys
97    A4 06 30 04 04 02 60 35  = Certificates 
98    A5 06 30 04 04 02 60 36  = TrustedCertificates
99    A7 06 30 04 04 02 60 37  = DataObjects
100    A8 06 30 04 04 02 60 38  = AuthObjects
101     
102    These are all PathOrObjects using the path CHOICE.  The paths are
103    octet strings of length 2.  Using this Path CHOICE is recommended,
104    so we only implement that for now.
105 */
106 static gpg_error_t
107 read_ef_odf (app_t app)
108 {
109   gpg_error_t err;
110   unsigned char *buffer, *p;
111   size_t buflen;
112   unsigned short value;
113
114   err = select_and_read_binary (app->slot, 0x5031, "ODF", &buffer, &buflen);
115   if (err)
116     return err;
117
118   if (len < 8)
119     {
120       log_error ("error: ODF too short\n");
121       xfree (buffer);
122       return gpg_error (GPG_ERR_INV_OBJ);
123     }
124   for (p=buffer; buflen >= 8; p += 8, buflen -= 8)
125     {
126       if ( (p[0] & 0xf0) != 0xA0
127            || memcmp (p+1, "\x06\x30\x04\x04\x02", 5) )
128         {
129           log_error ("ODF format is not supported by us\n");
130           xfree (buffer);
131           return gpg_error (GPG_ERR_INV_OBJ);
132         }
133       switch ((p[0] & 0x0f))
134         {
135         case 0: value = app->app_local->odf.private_keys; break;
136         case 1: value = app->app_local->odf.public_keys; break;
137         case 2: value = app->app_local->odf.trusted_public_keys; break;
138         case 3: value = app->app_local->odf.secret_keys; break;
139         case 4: value = app->app_local->odf.certificates; break;
140         case 5: value = app->app_local->odf.trusted_certificates; break;
141         case 6: value = app->app_local->odf.useful_certificates; break;
142         case 7: value = app->app_local->odf.data_objects; break;
143         case 8: value = app->app_local->odf.auth_objects; break;
144         default: value = 0; break;
145         }
146       if (value)
147         {
148           log_error ("duplicate object type %d in ODF ignored\n",(p[0)&0x0f));
149           continue;
150         }
151       value = ((p[6] << 8) | p[7]);
152       switch ((p[0] & 0x0f))
153         {
154         case 0: app->app_local->odf.private_keys = value; break;
155         case 1: app->app_local->odf.public_keys = value; break;
156         case 2: app->app_local->odf.trusted_public_keys = value; break;
157         case 3: app->app_local->odf.secret_keys = value; break;
158         case 4: app->app_local->odf.certificates = value; break;
159         case 5: app->app_local->odf.trusted_certificates = value; break;
160         case 6: app->app_local->odf.useful_certificates = value; break;
161         case 7: app->app_local->odf.data_objects = value; break;
162         case 8: app->app_local->odf.auth_objects = value; break;
163         default: 
164           log_error ("unknown object type %d in ODF ignored\n", (p[0)&0x0f));
165         }
166     }
167
168   if (buflen)
169     log_info ("warning: %u bytes of garbage detected at end of ODF\n", buflen);
170
171   xfree (buffer);
172   return 0;
173 }
174
175
176
177 /* Read and  parse the Private Key Directory Files. */
178 /*
179   6034 (privatekeys)
180
181 30 33 30 11 0C 08 53 4B 2E  43 48 2E 44 53 03 02   030...SK.CH.DS..
182 06 80 04 01 07 30 0C 04 01  01 03 03 06 00 40 02   .....0........@.
183 02 00 50 A1 10 30 0E 30 08  04 06 3F 00 40 16 00   ..P..0.0...?.@..
184 50 02 02 04 00 30 33 30 11  0C 08 53 4B 2E 43 48   P....030...SK.CH
185 2E 4B 45 03 02 06 80 04 01  0A 30 0C 04 01 0C 03   .KE.......0.....
186 03 06 44 00 02 02 00 52 A1  10 30 0E 30 08 04 06   ..D....R..0.0...
187 3F 00 40 16 00 52 02 02 04  00 30 34 30 12 0C 09   ?.@..R....040...
188 53 4B 2E 43 48 2E 41 55 54  03 02 06 80 04 01 0A   SK.CH.AUT.......
189 30 0C 04 01 0D 03 03 06 20  00 02 02 00 51 A1 10   0....... ....Q..
190 30 0E 30 08 04 06 3F 00 40  16 00 51 02 02 04 00   0.0...?.@..Q....
191 30 37 30 15 0C 0C 53 4B 2E  43 48 2E 44 53 2D 53   070...SK.CH.DS-S
192 50 58 03 02 06 80 04 01 0A  30 0C 04 01 02 03 03   PX.......0......
193 06 20 00 02 02 00 53 A1 10  30 0E 30 08 04 06 3F   . ....S..0.0...?
194 00 40 16 00 53 02 02 04 00  00 00 00 00 00 00 00   .@..S...........
195 00 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00   ................
196 00 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00   ................
197
198 */
199 static gpg_error_t
200 read_ef_prkdf (app_t app)
201 {
202
203
204 }
205
206 /* Read and  parse the Public Key Directory Files. */
207 static gpg_error_t
208 read_ef_pukdf (app_t app)
209 {
210
211
212 }
213
214
215 /* Read and parse the Certificate Directory Files. */
216 /* 
217
218 6035 (certificates)
219
220 30 2A 30 15 0C 0C 43 5F 58  35 30 39 2E 43 48 2E   0*0...C_X509.CH.
221 44 53 03 02 06 40 04 01 0A  30 03 04 01 01 A1 0C   DS...@...0......
222 30 0A 30 08 04 06 3F 00 40  16 C0 00 30 2A 30 15   0.0...?.@...0*0.
223 0C 0C 43 5F 58 35 30 39 2E  43 48 2E 4B 45 03 02   ..C_X509.CH.KE..
224 06 40 04 01 0A 30 03 04 01  0C A1 0C 30 0A 30 08   .@...0......0.0.
225 04 06 3F 00 40 16 C2 00 30  2B 30 16 0C 0D 43 5F   ..?.@...0+0...C_
226 58 35 30 39 2E 43 48 2E 41  55 54 03 02 06 40 04   X509.CH.AUT...@.
227 01 0A 30 03 04 01 0D A1 0C  30 0A 30 08 04 06 3F   ..0......0.0...?
228 00 40 16 C5 00 30 2E 30 19  0C 10 43 5F 58 35 30   .@...0.0...C_X50
229 39 2E 43 48 2E 44 53 2D 53  50 58 03 02 06 40 04   9.CH.DS-SPX...@.
230 01 0A 30 03 04 01 02 A1 0C  30 0A 30 08 04 06 3F   ..0......0.0...?
231 00 40 16 C1 20 00 00 00 00  00 00 00 00 00 00 00   .@.. ...........
232 00 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00   ................
233 00 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00   ................
234 00 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00   ................
235 00 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00   ................
236
237    0   42: SEQUENCE {
238    2   21:   SEQUENCE {   -- commonObjectAttributes
239    4   12:     UTF8String 'C_X509.CH.DS'
240   18    2:     BIT STRING 6 unused bits
241          :       '10'B (bit 1)
242   22    1:     OCTET STRING 0A
243          :     }
244   25    3:   SEQUENCE {   -- commonCertificateAttributes
245   27    1:     OCTET STRING 01
246          :     }
247   30   12:   [1] {        -- certAttributes
248   32   10:     SEQUENCE {
249   34    8:       SEQUENCE {
250   36    6:         OCTET STRING 3F 00 40 16 C0 00
251          :         }
252          :       }
253          :     }
254          :   }
255
256
257
258 6036 (trustedcertificates)
259
260 30 35 30 06 03 02 00 00 04  00 30 16 04 14 2D 36   050.......0...-6
261 33 39 33 33 39 34 30 33 39  37 37 36 34 30 31 32   3933940397764012
262 31 36 A1 13 30 11 30 0F 04  06 3F 00 40 16 C7 08   16..0.0...?.@...
263 02 01 00 80 02 02 29 30 35  30 06 03 02 00 00 04   ......)050......
264 00 30 16 04 14 2D 34 30 31  39 30 35 32 37 32 36   .0...-4019052726
265 38 30 31 36 39 33 34 39 32  A1 13 30 11 30 0F 04   801693492..0.0..
266 06 3F 00 40 16 C7 0E 02 01  00 80 02 04 12 30 34   .?.@..........04
267 30 06 03 02 00 00 04 00 30  15 04 13 37 39 36 33   0.......0...7963
268 32 38 33 36 35 30 37 36 36  34 38 32 39 36 30 A1   283650766482960.
269 13 30 11 30 0F 04 06 3F 00  40 16 C0 08 02 01 00   .0.0...?.@......
270 80 02 04 11 00 00 00 00 00  00 00 00 00 00 00 00   ................
271 00 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00   ................
272
273    0   53: SEQUENCE {
274    2    6:   SEQUENCE {
275    4    2:     BIT STRING
276          :       '00000000'B
277          :       Error: Spurious zero bits in bitstring.
278    8    0:     OCTET STRING
279          :       Error: Object has zero length.
280          :     }
281   10   22:   SEQUENCE {
282   12   20:     OCTET STRING '-6393394039776401216'
283          :     }
284   34   19:   [1] {
285   36   17:     SEQUENCE {
286   38   15:       SEQUENCE {
287   40    6:         OCTET STRING 3F 00 40 16 C7 08
288   48    1:         INTEGER 0       -- index
289   51    2:         [0] 02 29       -- length
290          :         }
291          :       }
292          :     }
293          :   }
294
295
296 */
297 static gpg_error_t
298 read_ef_cdf (app_t app)
299 {
300   gpg_error_t err;
301   unsigned char *buffer = NULL;
302   size_t buflen;
303   unsigned short value;
304   unsigned short fid;
305   const unsigned char *p;
306   size_t n, objlen, hdrlen;
307   int class, tag, constructed, ndef;
308   
309   fid = app->app_local->odf.certificates;
310   if (!fid)
311     return 0; /* No certificates. */
312   
313   err = select_and_read_binary (app->slot, fid, "CDF", &buffer, &buflen);
314   if (err)
315     return err;
316   
317   p = buffer;
318   n = buflen;
319
320   /* Loop over the records.  We stop as soon as we detect a new record
321      starting with 0x00 or 0xff as these values are commonly used to pad
322      the the read datablocks and are no valid ASN.1 encoding. */
323   while (n && *p && *p == 0xff)
324     {
325       const unsigned char *pp;
326       size_t nn;
327
328       err = parse_ber_header (&p, &n, &class, &tag, &constructed,
329                               &ndef, &objlen, &hdrlen);
330       if (!err && (objlen > n || tag != TAG_SEQUENCE))
331         err = gpg_error (GPG_ERR_INV_OBJ);
332       if (err)
333         {
334           log_error ("error parsing CDF record: %s\n", gpg_strerror (err));
335           goto leave;
336         }
337       pp = p;
338       nn = objlen;
339       p += objlen;
340       n -= objlen;
341
342       /* Skip the commonObjectAttributes.  */
343       err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
344                               &ndef, &objlen, &hdrlen);
345       if (!err && (objlen > nn || tag != TAG_SEQUENCE))
346         err = gpg_error (GPG_ERR_INV_OBJ);
347       if (err)
348         {
349           log_error ("error parsing CDF record: %s - skipped\n",
350                      gpg_strerror (err));
351           continue;
352         }
353       pp += objlen;
354       nn -= objlen;
355
356       /* Skip the commonCertificateAttributes.  */
357       err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
358                               &ndef, &objlen, &hdrlen);
359       if (!err && (objlen > nn || tag != TAG_SEQUENCE))
360         err = gpg_error (GPG_ERR_INV_OBJ);
361       if (err)
362         {
363           log_error ("error parsing CDF record: %s - skipped\n",
364                      gpg_strerror (err));
365           continue;
366         }
367       pp += objlen;
368       nn -= objlen;
369
370       /* FIXME: Check that this is a reference to a certificate. */
371
372
373     }
374
375
376  leave:
377   xfree (buffer);
378   return err;
379 }
380
381 /* Read and parse Authentication Object Directory Files.  */
382 static gpg_error_t 
383 read_ef_aodf (app_t app)
384 {
385
386 }
387
388
389 /* 6037 (dataobjects)
390
391 30 1E 30 0B 0C 06 45 46 2E  47 44 4F 04 01 0A 30   0.0...EF.GDO...0
392 02 0C 00 A1 0B 30 09 04 04  3F 00 2F 02 80 01 0E   .....0...?./....
393 30 30 30 18 0C 0F 64 69 73  70 6C 61 79 20 6D 65   000...display me
394 73 73 61 67 65 03 02 06 C0  04 01 0A 30 05 0C 03   ssage.......0...
395 42 53 53 A1 0D 30 0B 04 06  3F 00 40 16 D0 00 80   BSS..0...?.@....
396 01 20 30 2B 30 0C 0C 03 53  53 4F 03 02 06 C0 04   . 0+0...SSO.....
397 01 0A 30 0B 0C 09 53 61 66  65 47 75 61 72 64 A1   ..0...SafeGuard.
398 0E 30 0C 04 06 3F 00 0F FF  30 02 80 02 03 00 30   .0...?...0.....0
399 30 30 11 0C 08 53 47 41 53  64 61 74 61 03 02 06   00...SGASdata...
400 C0 04 01 0A 30 0B 0C 09 53  61 66 65 47 75 61 72   ....0...SafeGuar
401 64 A1 0E 30 0C 04 06 3F 00  0F FF 40 01 80 02 00   d..0...?...@....
402 80 30 30 30 11 0C 08 55 73  65 72 64 61 74 61 03   .000...Userdata.
403 02 06 40 04 01 0A 30 0B 0C  09 53 61 66 65 47 75   ..@...0...SafeGu
404 61 72 64 A1 0E 30 0C 04 06  3F 00 0F FF 30 01 80   ard..0...?...0..
405 02 01 00 30 2C 30 13 0C 0A  62 61 73 69 63 20 64   ...0,0...basic d
406 61 74 61 03 02 06 C0 04 01  0A 30 05 0C 03 49 44   ata.......0...ID
407 44 A1 0E 30 0C 04 06 3F 00  40 17 D0 01 80 02 02   D..0...?.@......
408 00 30 2F 30 16 0C 0D 65 78  74 65 6E 64 65 64 20   .0/0...extended 
409 64 61 74 61 03 02 06 C0 04  01 0A 30 05 0C 03 49   data.......0...I
410 44 44 A1 0E 30 0C 04 06 3F  00 40 17 D0 02 80 02   DD..0...?.@.....
411 08 00 30 34 30 1B 0C 12 73  70 65 63 69 61 6C 20   ..040...special 
412 70 72 69 76 69 6C 65 67 65  73 03 02 06 C0 04 01   privileges......
413 0A 30 05 0C 03 49 44 44 A1  0E 30 0C 04 06 3F 00   .0...IDD..0...?.
414 40 17 D0 03 80 02 04 00                            @.......        
415
416    0   30: SEQUENCE {
417    2   11:   SEQUENCE {
418    4    6:     UTF8String 'EF.GDO'
419   12    1:     OCTET STRING 0A
420          :     }
421   15    2:   SEQUENCE {
422   17    0:     UTF8String
423          :       Error: Object has zero length.
424          :     }
425   19   11:   [1] {
426   21    9:     SEQUENCE {
427   23    4:       OCTET STRING 3F 00 2F 02
428   29    1:       [0] 0E
429          :       }
430          :     }
431          :   }
432
433
434
435 6038 (authobjects)
436
437 30 2A 30 0B 0C 05 62 61 73  69 63 03 02 00 C0 30   0*0...basic....0
438 03 04 01 0A A1 16 30 14 03  03 00 0C 10 0A 01 01   ......0.........
439 02 01 06 02 01 06 02 01 08  80 01 01 30 51 30 19   ............0Q0.
440 0C 13 73 70 65 63 69 66 69  63 20 50 49 4E 20 66   ..specific PIN f
441 6F 72 20 44 53 03 02 00 C0  30 03 04 01 07 A1 2F   or DS....0...../
442 30 2D 03 03 00 4C 10 0A 01  01 02 01 06 02 01 06   0-...L..........
443 02 01 08 80 01 02 18 0F 32  30 30 32 30 34 31 39   ........20020419
444 31 32 31 33 34 31 5A 30 06  04 04 3F 00 40 16      121341Z0...?.@. 
445
446    0   42: SEQUENCE {
447    2   11:   SEQUENCE {
448    4    5:     UTF8String 'basic'
449   11    2:     BIT STRING
450          :       '00000011'B
451          :       Error: Spurious zero bits in bitstring.
452          :     }
453   15    3:   SEQUENCE {
454   17    1:     OCTET STRING 0A
455          :     }
456   20   22:   [1] {
457   22   20:     SEQUENCE {
458   24    3:       BIT STRING
459          :         '0000100000110000'B
460          :         Error: Spurious zero bits in bitstring.
461   29    1:       ENUMERATED 1
462   32    1:       INTEGER 6
463   35    1:       INTEGER 6
464   38    1:       INTEGER 8
465   41    1:       [0] 01
466          :       }
467          :     }
468          :   }
469
470
471
472 */
473
474
475 /* Read and parse the EF(TokenInfo). 
476
477 TokenInfo ::= SEQUENCE {
478     version             INTEGER {v1(0)} (v1,...),
479     serialNumber        OCTET STRING,
480     manufacturerID      Label OPTIONAL,
481     label               [0] Label OPTIONAL,
482     tokenflags          TokenFlags,
483     seInfo              SEQUENCE OF SecurityEnvironmentInfo OPTIONAL,
484     recordInfo          [1] RecordInfo OPTIONAL,
485     supportedAlgorithms [2] SEQUENCE OF AlgorithmInfo OPTIONAL,
486     ...,
487     issuerId            [3] Label OPTIONAL,
488     holderId            [4] Label OPTIONAL,
489     lastUpdate          [5] LastUpdate OPTIONAL,
490     preferredLanguage   PrintableString OPTIONAL -- In accordance with
491     -- IETF RFC 1766 
492 } (CONSTRAINED BY { -- Each AlgorithmInfo.reference value must be unique --})
493
494 TokenFlags ::= BIT STRING {
495     readonly            (0),
496     loginRequired       (1),
497     prnGeneration       (2),
498     eidCompliant        (3)
499 }
500
501
502  5032:
503
504 30 31 02 01 00 04 04 05 45  36 9F 0C 0C 44 2D 54   01......E6...D-T
505 72 75 73 74 20 47 6D 62 48  80 14 4F 66 66 69 63   rust GmbH..Offic
506 65 20 69 64 65 6E 74 69 74  79 20 63 61 72 64 03   e identity card.
507 02 00 40 20 63 61 72 64 03  02 00 40 00 00 00 00   ..@ card...@....
508 00 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00   ................
509
510    0   49: SEQUENCE {
511    2    1:   INTEGER 0
512    5    4:   OCTET STRING 05 45 36 9F
513   11   12:   UTF8String 'D-Trust GmbH'
514   25   20:   [0] 'Office identity card'
515   47    2:   BIT STRING
516          :     '00000010'B (bit 1)
517          :     Error: Spurious zero bits in bitstring.
518          :   }
519
520
521
522
523  */
524 static gpg_error_t
525 read_ef_tokeninfo (app_t app)
526 {
527   unsigned short efid = 0x5032;
528
529 }
530
531
532 /* Get all the basic information from the pkcs#15 card, check the
533    structure and init our context.  This is used once at application
534    initialization. */
535 static gpg_error_t
536 read_p15_info (app_t app)
537 {
538   gpg_error_t err;
539
540   err = read_ed_odf (app);
541   if (err)
542     return err;
543
544 }
545
546
547 static int
548 do_learn_status (APP app, CTRL ctrl)
549 {
550   gpg_error_t err;
551   char ct_buf[100], id_buf[100];
552   int i;
553
554   /* Output information about all useful objects. */
555   for (i=0; objlist[i].fid; i++)
556     {
557       if (filelist[i].certtype)
558         {
559           size_t len;
560
561           len = app_help_read_length_of_cert (app->slot,
562                                               filelist[i].fid, NULL);
563           if (len)
564             {
565               /* FIXME: We should store the length in the application's
566                  context so that a following readcert does only need to
567                  read that many bytes. */
568               sprintf (ct_buf, "%d", filelist[i].certtype);
569               sprintf (id_buf, "P15-DF01.%04X", filelist[i].fid);
570               send_status_info (ctrl, "CERTINFO",
571                                 ct_buf, strlen (ct_buf), 
572                                 id_buf, strlen (id_buf), 
573                                 NULL, (size_t)0);
574             }
575         }
576       else if (filelist[i].iskeypair)
577         {
578           char gripstr[40+1];
579
580           err = keygripstr_from_pk_file (app->slot, filelist[i].fid, gripstr);
581           if (err)
582             log_error ("can't get keygrip from FID 0x%04X: %s\n",
583                        filelist[i].fid, gpg_strerror (err));
584           else
585             {
586               sprintf (id_buf, "P15-DF01.%04X", filelist[i].fid);
587               send_status_info (ctrl, "KEYPAIRINFO",
588                                 gripstr, 40, 
589                                 id_buf, strlen (id_buf), 
590                                 NULL, (size_t)0);
591             }
592         }
593     }
594
595   return 0;
596 }
597
598
599
600
601 /* Release all resources.  */
602 static void
603 do_deinit (app_t app)
604 {
605   if (app && app->app_local)
606     {
607       xfree (app->app_local);
608       app->app_local = NULL;
609     }
610 }
611
612
613 /* Select the PKCS#15 application on the card in SLOT.  */
614 int
615 app_select_p15 (APP app)
616 {
617   static char const aid[] = { 0xA0, 0, 0, 0, 0x63,
618                               0x50, 0x4B, 0x43, 0x53, 0x2D, 0x31, 0x35 };
619   int slot = app->slot;
620   int rc;
621   
622   rc = iso7816_select_application (slot, aid, sizeof aid);
623   if (!rc)
624     {
625       app->apptype = "P15";
626
627       app->app_local = xtrycalloc (1, sizeof *app->app_local);
628       if (!app->app_local)
629         {
630           rc = gpg_error_from_errno (errno);
631           goto leave;
632         }
633
634       /* Read basic information and check whether this is a real
635          card.  */
636       rc = read_p15_info (app);
637       
638       /* Special serial number munging.  We need to do one case here
639          because we need to access the EF(TokenInfo).  */
640       if (app->serialnolen == 12
641           && !memcmp (app->serial, "\xD2\x76\0\0\0\0\0\0\0\0\0\0", 12))
642         {
643           /* This is a German card with a silly serial number.  Try to get
644              the serial number from the EF(TokenInfo). We indicate such a
645              serial number by the using the prefix: "FF0100". */
646           const char *efser = card->p15card->serial_number;
647           char *p;
648           
649           if (!efser)
650             efser = "";
651           
652           xfree (*serial);
653           *serial = NULL;
654           p = xtrymalloc (strlen (efser) + 7);
655           if (!p)
656             rc = gpg_error (gpg_err_code_from_errno (errno));
657           else
658             {
659               strcpy (p, "FF0100");
660               strcpy (p+6, efser);
661               *serial = p;
662             }
663         }
664       else
665         rc = app_munge_serialno (app);
666
667       app->fnc.deinit = do_deinit;
668       app->fnc.learn_status = do_learn_status;
669       app->fnc.readcert = do_readcert;
670       app->fnc.getattr = NULL;
671       app->fnc.setattr = NULL;
672       app->fnc.genkey = NULL;
673       app->fnc.sign = do_sign;
674       app->fnc.auth = NULL;
675       app->fnc.decipher = do_decipher;
676       app->fnc.change_pin = NULL;
677       app->fnc.check_pin = NULL;
678
679     leave:
680       if (rc)
681         {
682           xfree (app->app_local);
683           app->app_local = NULL;
684         }
685       
686    }
687
688   return rc;
689 }
690
691