69f12f43a928ea8c33baf72392faec03fef4037d
[gnupg.git] / scd / app-piv.c
1 /* app-piv.c - The OpenPGP card application.
2  * Copyright (C) 2019 g10 Code GmbH
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 3 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, see <https://www.gnu.org/licenses/>.
18  */
19
20 /* Some notes:
21  * - Specs for PIV are at http://dx.doi.org/10.6028/NIST.SP.800-73-4
22  *
23  */
24
25 #include <config.h>
26 #include <errno.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <stdarg.h>
30 #include <string.h>
31 #include <time.h>
32
33 #include "scdaemon.h"
34
35 #include "../common/util.h"
36 #include "../common/i18n.h"
37 #include "iso7816.h"
38 #include "app-common.h"
39 #include "../common/tlv.h"
40 #include "../common/host2net.h"
41 #include "apdu.h" /* We use apdu_send_direct.  */
42
43 #define PIV_ALGORITHM_3DES_ECB_0 0x00
44 #define PIV_ALGORITHM_2DES_ECB   0x01
45 #define PIV_ALGORITHM_2DES_CBC   0x02
46 #define PIV_ALGORITHM_3DES_ECB   0x03
47 #define PIV_ALGORITHM_3DES_CBC   0x04
48 #define PIV_ALGORITHM_RSA        0x07
49 #define PIV_ALGORITHM_AES128_ECB 0x08
50 #define PIV_ALGORITHM_AES128_CBC 0x09
51 #define PIV_ALGORITHM_AES192_ECB 0x0A
52 #define PIV_ALGORITHM_AES192_CBC 0x0B
53 #define PIV_ALGORITHM_AES256_ECB 0x0C
54 #define PIV_ALGORITHM_AES256_CBC 0x0D
55 #define PIV_ALGORITHM_ECC_P256   0x11
56 #define PIV_ALGORITHM_ECC_P384   0x14
57
58
59
60 /* A table describing the DOs of a PIV card.  */
61 struct data_object_s
62 {
63   unsigned int tag;
64   unsigned int mandatory:1;
65   unsigned int acr_contact:2;     /* 0=always, 1=VCI, 2=PIN, 3=PINorOCC */
66   unsigned int acr_contactless:2; /* 0=always, 1=VCI, 2=VCIandPIN,
67                                                       3=VCIand(PINorOCC) */
68   unsigned int binary:1;          /* Data is not human readable.  */
69   unsigned int dont_cache:1;      /* Data item will not be cached.  */
70   unsigned int flush_on_error:1;  /* Flush cached item on error.  */
71   unsigned int keypair:1;         /* Has a public key for a keypair.  */
72   char keyref[3];                 /* The key reference.  */
73   char *oidsuffix; /* Suffix of the OID, prefix is "2.16.840.1.101.3.7." */
74   char *desc;                     /* Description of the DO.  */
75 };
76 typedef struct data_object_s *data_object_t;
77 static struct data_object_s data_objects[] = {
78   { 0x5FC107, 1, 0,1, 1, 0,0, 0, "",   "1.219.0", "Card Capability Container"},
79   { 0x5FC102, 1, 0,0, 1, 0,0, 0, "",   "2.48.0",  "Cardholder Unique Id" },
80   { 0x5FC105, 1, 0,1, 1, 0,0, 1, "9A", "2.1.1",   "Cert PIV Authentication" },
81   { 0x5FC103, 1, 2,2, 1, 0,0, 0, "",   "2.96.16", "Cardholder Fingerprints" },
82   { 0x5FC106, 1, 0,1, 1, 0,0, 0, "",   "2.144.0", "Security Object" },
83   { 0x5FC108, 1, 2,2, 1, 0,0, 0, "",   "2.96.48", "Cardholder Facial Image" },
84   { 0x5FC101, 1, 0,0, 1, 0,0, 1, "9E", "2.5.0",   "Cert Card Authentication"},
85   { 0x5FC10A, 0, 0,1, 1, 0,0, 1, "9C", "2.1.0",   "Cert Digital Signature" },
86   { 0x5FC10B, 0, 0,1, 1, 0,0, 1, "9D", "2.1.2",   "Cert Key Management" },
87   { 0x5FC109, 0, 3,3, 0, 0,0, 0, "",   "2.48.1",  "Printed Information" },
88   { 0x7E,     0, 0,0, 1, 0,0, 0, "",   "2.96.80", "Discovery Object" },
89   { 0x5FC10C, 0, 0,1, 1, 0,0, 0, "",   "2.96.96", "Key History Object" },
90   { 0x5FC10D, 0, 0,1, 1, 0,0, 0, "82", "2.16.1",  "Retired Cert Key Mgm 1" },
91   { 0x5FC10E, 0, 0,1, 1, 0,0, 0, "83", "2.16.2",  "Retired Cert Key Mgm 2" },
92   { 0x5FC10F, 0, 0,1, 1, 0,0, 0, "84", "2.16.3",  "Retired Cert Key Mgm 3" },
93   { 0x5FC110, 0, 0,1, 1, 0,0, 0, "85", "2.16.4",  "Retired Cert Key Mgm 4" },
94   { 0x5FC111, 0, 0,1, 1, 0,0, 0, "86", "2.16.5",  "Retired Cert Key Mgm 5" },
95   { 0x5FC112, 0, 0,1, 1, 0,0, 0, "87", "2.16.6",  "Retired Cert Key Mgm 6" },
96   { 0x5FC113, 0, 0,1, 1, 0,0, 0, "88", "2.16.7",  "Retired Cert Key Mgm 7" },
97   { 0x5FC114, 0, 0,1, 1, 0,0, 0, "89", "2.16.8",  "Retired Cert Key Mgm 8" },
98   { 0x5FC115, 0, 0,1, 1, 0,0, 0, "8A", "2.16.9",  "Retired Cert Key Mgm 9" },
99   { 0x5FC116, 0, 0,1, 1, 0,0, 0, "8B", "2.16.10", "Retired Cert Key Mgm 10" },
100   { 0x5FC117, 0, 0,1, 1, 0,0, 0, "8C", "2.16.11", "Retired Cert Key Mgm 11" },
101   { 0x5FC118, 0, 0,1, 1, 0,0, 0, "8D", "2.16.12", "Retired Cert Key Mgm 12" },
102   { 0x5FC119, 0, 0,1, 1, 0,0, 0, "8E", "2.16.13", "Retired Cert Key Mgm 13" },
103   { 0x5FC11A, 0, 0,1, 1, 0,0, 0, "8F", "2.16.14", "Retired Cert Key Mgm 14" },
104   { 0x5FC11B, 0, 0,1, 1, 0,0, 0, "90", "2.16.15", "Retired Cert Key Mgm 15" },
105   { 0x5FC11C, 0, 0,1, 1, 0,0, 0, "91", "2.16.16", "Retired Cert Key Mgm 16" },
106   { 0x5FC11D, 0, 0,1, 1, 0,0, 0, "92", "2.16.17", "Retired Cert Key Mgm 17" },
107   { 0x5FC11E, 0, 0,1, 1, 0,0, 0, "93", "2.16.18", "Retired Cert Key Mgm 18" },
108   { 0x5FC11F, 0, 0,1, 1, 0,0, 0, "94", "2.16.19", "Retired Cert Key Mgm 19" },
109   { 0x5FC120, 0, 0,1, 1, 0,0, 0, "95", "2.16.20", "Retired Cert Key Mgm 20" },
110   { 0x5FC121, 0, 2,2, 1, 0,0, 0, "",   "2.16.21", "Cardholder Iris Images" },
111   { 0x7F61,   0, 0,0, 1, 0,0, 0, "",   "2.16.22", "BIT Group Template" },
112   { 0x5FC122, 0, 0,0, 1, 0,0, 0, "",   "2.16.23", "SM Cert Signer" },
113   { 0x5FC123, 0, 3,3, 1, 0,0, 0, "",   "2.16.24", "Pairing Code Ref Data" },
114   { 0 }
115   /* Other key reference values without a tag:
116    * "00" Global PIN (not cleared by application switching)
117    * "04" PIV Secure Messaging Key
118    * "80" PIV Application PIN
119    * "81" PIN Unblocking Key
120    * "96" Primary Finger OCC
121    * "97" Secondary Finger OCC
122    * "98" Pairing Code
123    * "9B" PIV Card Application Administration Key
124    */
125 };
126
127
128 /* One cache item for DOs.  */
129 struct cache_s {
130   struct cache_s *next;
131   int tag;
132   size_t length;
133   unsigned char data[1];
134 };
135
136
137 /* Object with application specific data.  */
138 struct app_local_s {
139   /* A linked list with cached DOs.  */
140   struct cache_s *cache;
141
142   /* Various flags.  */
143   struct
144   {
145     unsigned int dummy:1;
146   } flags;
147
148 };
149
150
151 /***** Local prototypes  *****/
152 static gpg_error_t get_keygrip_by_tag (app_t app, unsigned int tag,
153                                        char **r_keygripstr);
154
155
156
157
158 \f
159 /* Deconstructor. */
160 static void
161 do_deinit (app_t app)
162 {
163   if (app && app->app_local)
164     {
165       struct cache_s *c, *c2;
166
167       for (c = app->app_local->cache; c; c = c2)
168         {
169           c2 = c->next;
170           xfree (c);
171         }
172
173       xfree (app->app_local);
174       app->app_local = NULL;
175     }
176 }
177
178
179 /* Wrapper around iso7816_get_data which first tries to get the data
180  * from the cache.  With GET_IMMEDIATE passed as true, the cache is
181  * bypassed.  The tag-53 container is also removed.  */
182 static gpg_error_t
183 get_cached_data (app_t app, int tag,
184                  unsigned char **result, size_t *resultlen,
185                  int get_immediate)
186 {
187   gpg_error_t err;
188   int i;
189   unsigned char *p;
190   const unsigned char *s;
191   size_t len, n;
192   struct cache_s *c;
193
194   *result = NULL;
195   *resultlen = 0;
196
197   if (!get_immediate)
198     {
199       for (c=app->app_local->cache; c; c = c->next)
200         if (c->tag == tag)
201           {
202             if(c->length)
203               {
204                 p = xtrymalloc (c->length);
205                 if (!p)
206                   return gpg_error_from_syserror ();
207                 memcpy (p, c->data, c->length);
208                 *result = p;
209               }
210
211             *resultlen = c->length;
212
213             return 0;
214           }
215     }
216
217   err = iso7816_get_data_odd (app->slot, 0, tag, &p, &len);
218   if (err)
219     return err;
220
221   /* Unless the Discovery Object or the BIT Group Template is
222    * requested, remove the outer container.
223    * (SP800-73.4 Part 2, section 3.1.2)   */
224   if (tag == 0x7E || tag == 0x7F61)
225     ;
226   else if (len && *p == 0x53 && (s = find_tlv (p, len, 0x53, &n)))
227     {
228       memmove (p, s, n);
229       len = n;
230     }
231
232   if (len)
233     *result = p;
234   *resultlen = len;
235
236   /* Check whether we should cache this object. */
237   if (get_immediate)
238     return 0;
239
240   for (i=0; data_objects[i].tag; i++)
241     if (data_objects[i].tag == tag)
242       {
243         if (data_objects[i].dont_cache)
244           return 0;
245         break;
246       }
247
248   /* Okay, cache it. */
249   for (c=app->app_local->cache; c; c = c->next)
250     log_assert (c->tag != tag);
251
252   c = xtrymalloc (sizeof *c + len);
253   if (c)
254     {
255       if (len)
256         memcpy (c->data, p, len);
257       else
258         xfree (p);
259       c->length = len;
260       c->tag = tag;
261       c->next = app->app_local->cache;
262       app->app_local->cache = c;
263     }
264
265   return 0;
266 }
267
268
269 /* Get the DO identified by TAG from the card in SLOT and return a
270  * buffer with its content in RESULT and NBYTES.  The return value is
271  * NULL if not found or a pointer which must be used to release the
272  * buffer holding value.  */
273 static void *
274 get_one_do (app_t app, int tag, unsigned char **result, size_t *nbytes,
275             int *r_err)
276 {
277   gpg_error_t err;
278   int i;
279   unsigned char *buffer;
280   size_t buflen;
281   unsigned char *value;
282   size_t valuelen;
283   gpg_error_t dummyerr;
284
285   if (!r_err)
286     r_err = &dummyerr;
287
288   *result = NULL;
289   *nbytes = 0;
290   *r_err = 0;
291   for (i=0; data_objects[i].tag && data_objects[i].tag != tag; i++)
292     ;
293
294   value = NULL;
295   err = gpg_error (GPG_ERR_ENOENT);
296
297   if (!value) /* Not in a constructed DO, try simple. */
298     {
299       err = get_cached_data (app, tag, &buffer, &buflen,
300                              data_objects[i].dont_cache);
301       if (!err)
302         {
303           value = buffer;
304           valuelen = buflen;
305         }
306     }
307
308   if (!err)
309     {
310       *nbytes = valuelen;
311       *result = value;
312       return buffer;
313     }
314
315   *r_err = err;
316   return NULL;
317 }
318
319
320 static void
321 dump_all_do (int slot)
322 {
323   gpg_error_t err;
324   int i;
325   unsigned char *buffer;
326   size_t buflen;
327
328   for (i=0; data_objects[i].tag; i++)
329     {
330       /* We don't try extended length APDU because such large DO would
331          be pretty useless in a log file.  */
332       err = iso7816_get_data_odd (slot, 0, data_objects[i].tag,
333                                  &buffer, &buflen);
334       if (err)
335         {
336           if (gpg_err_code (err) == GPG_ERR_ENOENT
337               && !data_objects[i].mandatory)
338             ;
339           else
340             log_info ("DO '%s' not available: %s\n",
341                       data_objects[i].desc, gpg_strerror (err));
342         }
343       else
344         {
345           if (data_objects[i].binary)
346             {
347               log_info ("DO '%s': ", data_objects[i].desc);
348               if (buflen > 16 && opt.verbose < 2)
349                 {
350                   log_printhex (buffer, 16, NULL);
351                   log_printf ("[...]\n");
352                 }
353               else
354                 log_printhex (buffer, buflen, "");
355             }
356           else
357             log_info ("DO '%s': '%.*s'\n",
358                       data_objects[i].desc,
359                       (int)buflen, buffer);
360
361         }
362       xfree (buffer); buffer = NULL;
363     }
364 }
365
366
367 /* Parse the key reference KEYREFSTR which is expected to hold a key
368  * reference for a PIN object.  Return the one octet keyref or -1 for
369  * an invalid reference.  */
370 static int
371 parse_pin_keyref (const char *keyrefstr)
372 {
373   if (!keyrefstr)
374     return -1;
375   else if (!ascii_strcasecmp (keyrefstr, "PIV.00"))
376     return 0x00;
377   else if (!ascii_strcasecmp (keyrefstr, "PIV.80"))
378     return 0x80;
379   else if (!ascii_strcasecmp (keyrefstr, "PIV.81"))
380     return 0x81;
381   else
382     return -1;
383 }
384
385
386 /* Return an allocated string with the serial number in a format to be
387  * show to the user.  With FAILMODE is true return NULL if such an
388  * abbreviated S/N is not available, else return the full serial
389  * number as a hex string.  May return NULL on malloc problem.  */
390 static char *
391 get_dispserialno (app_t app, int failmode)
392 {
393   char *result;
394
395   if (app->serialno && app->serialnolen == 3+1+4
396       && !memcmp (app->serialno, "\xff\x02\x00", 3))
397     {
398       /* This is a 4 byte S/N of a Yubikey which seems to be printed
399        * on the token in decimal.  Maybe they will print larger S/N
400        * also in decimal but we can't be sure, thus do it only for
401        * these 32 bit numbers.  */
402       unsigned long sn;
403       sn  = app->serialno[4] * 16777216;
404       sn += app->serialno[5] * 65536;
405       sn += app->serialno[6] * 256;
406       sn += app->serialno[7];
407       result = xtryasprintf ("yk-%lu", sn);
408     }
409   else if (failmode)
410     result = NULL;  /* No Abbreviated S/N.  */
411   else
412     result = app_get_serialno (app);
413
414   return result;
415 }
416
417
418 /* The verify command can be used to retrieve the security status of
419  * the card.  Given the PIN name (e.g. "PIV.80" for thge application
420  * pin, a status is returned:
421  *
422  *        -1 = Error retrieving the data,
423  *        -2 = No such PIN,
424  *        -3 = PIN blocked,
425  *        -5 = Verify still valid,
426  *    n >= 0 = Number of verification attempts left.
427  */
428 static int
429 get_chv_status (app_t app, const char *keyrefstr)
430 {
431   unsigned char apdu[4];
432   unsigned int sw;
433   int result;
434   int keyref;
435
436   keyref = parse_pin_keyref (keyrefstr);
437   if (!keyrefstr)
438     return -1;
439
440   apdu[0] = 0x00;
441   apdu[1] = ISO7816_VERIFY;
442   apdu[2] = 0x00;
443   apdu[3] = keyref;
444   if (!iso7816_apdu_direct (app->slot, apdu, 4, 0, &sw, NULL, NULL))
445     result = -5; /* No need to verification.  */
446   else if (sw == 0x6a88)
447     result = -2; /* No such PIN.  */
448   else if (sw == 0x6983)
449     result = -3; /* PIN is blocked.  */
450   else if ((sw & 0xfff0) == 0x63C0)
451     result = (sw & 0x000f);
452   else
453     result = -1; /* Error.  */
454
455   return result;
456 }
457
458
459 /* Implementation of the GETATTR command.  This is similar to the
460  * LEARN command but returns only one value via status lines.  */
461 static gpg_error_t
462 do_getattr (app_t app, ctrl_t ctrl, const char *name)
463 {
464   static struct {
465     const char *name;
466     int tag;
467     int special;
468   } table[] = {
469     { "SERIALNO",     0x0000, -1 },
470     { "$AUTHKEYID",   0x0000, -2 }, /* Default key for ssh.  */
471     { "$DISPSERIALNO",0x0000, -3 },
472     { "CHV-STATUS",   0x0000, -4 }
473   };
474   gpg_error_t err = 0;
475   int idx;
476   void *relptr;
477   unsigned char *value;
478   size_t valuelen;
479
480   for (idx=0; (idx < DIM (table)
481                && ascii_strcasecmp (table[idx].name, name)); idx++)
482     ;
483   if (!(idx < DIM (table)))
484     err = gpg_error (GPG_ERR_INV_NAME);
485   else if (table[idx].special == -1)
486     {
487       char *serial = app_get_serialno (app);
488
489       if (serial)
490         {
491           send_status_direct (ctrl, "SERIALNO", serial);
492           xfree (serial);
493         }
494     }
495   else if (table[idx].special == -2)
496     {
497       char const tmp[] = "PIV.9A"; /* Cert PIV Authenticate.  */
498       send_status_info (ctrl, table[idx].name, tmp, strlen (tmp), NULL, 0);
499     }
500   else if (table[idx].special == -3)
501     {
502       char *tmp = get_dispserialno (app, 1);
503
504       if (tmp)
505         {
506           send_status_info (ctrl, table[idx].name,
507                             tmp, strlen (tmp),
508                             NULL, (size_t)0);
509           xfree (tmp);
510         }
511       else
512         err = gpg_error (GPG_ERR_INV_NAME);  /* No Abbreviated S/N.  */
513     }
514   else if (table[idx].special == -4) /* CHV-STATUS */
515     {
516       int tmp[3];
517
518       tmp[0] = get_chv_status (app, "PIV.00");
519       tmp[1] = get_chv_status (app, "PIV.80");
520       tmp[2] = get_chv_status (app, "PIV.81");
521       err = send_status_printf (ctrl, table[idx].name, "%d %d %d",
522                                 tmp[0], tmp[1], tmp[2]);
523     }
524   else
525     {
526       relptr = get_one_do (app, table[idx].tag, &value, &valuelen, &err);
527       if (relptr)
528         {
529           send_status_info (ctrl, table[idx].name, value, valuelen, NULL, 0);
530           xfree (relptr);
531         }
532     }
533
534   return err;
535 }
536
537
538 /* Send the KEYPAIRINFO back.  DOBJ describes the data object carrying
539  * the key.  This is used by the LEARN command. */
540 static gpg_error_t
541 send_keypair_and_cert_info (app_t app, ctrl_t ctrl, data_object_t dobj,
542                             int only_keypair)
543 {
544   gpg_error_t err = 0;
545   char *keygripstr = NULL;
546   char idbuf[50];
547
548   err = get_keygrip_by_tag (app, dobj->tag, &keygripstr);
549   if (err)
550     goto leave;
551
552   snprintf (idbuf, sizeof idbuf, "PIV.%s", dobj->keyref);
553   send_status_info (ctrl, "KEYPAIRINFO",
554                     keygripstr, strlen (keygripstr),
555                     idbuf, strlen (idbuf),
556                     NULL, (size_t)0);
557   if (!only_keypair)
558     {
559       /* All certificates are of type 100 (Regular X.509 Cert).  */
560       send_status_info (ctrl, "CERTINFO",
561                         "100", 3,
562                         idbuf, strlen (idbuf),
563                         NULL, (size_t)0);
564     }
565
566  leave:
567   xfree (keygripstr);
568   return err;
569 }
570
571
572 /* Handle the LEARN command.  */
573 static gpg_error_t
574 do_learn_status (app_t app, ctrl_t ctrl, unsigned int flags)
575 {
576   int i;
577
578   (void)flags;
579
580   do_getattr (app, ctrl, "CHV-STATUS");
581
582   for (i=0; data_objects[i].tag; i++)
583     if (data_objects[i].keypair)
584       send_keypair_and_cert_info (app, ctrl, data_objects + i, !!(flags & 1));
585
586
587   return 0;
588 }
589
590
591 /* Core of do-readcert which fetches the certificate based on the
592  * given tag and returns it in a freshly allocated buffer stored at
593  * R_CERT and the length of the certificate stored at R_CERTLEN.  */
594 static gpg_error_t
595 readcert_by_tag (app_t app, unsigned int tag,
596                  unsigned char **r_cert, size_t *r_certlen)
597 {
598   gpg_error_t err;
599   unsigned char *buffer;
600   size_t buflen;
601   void *relptr;
602   const unsigned char *s;
603   size_t n;
604
605   *r_cert = NULL;
606   *r_certlen = 0;
607
608   relptr = get_one_do (app, tag, &buffer, &buflen, NULL);
609   if (!relptr || !buflen)
610    {
611       err = gpg_error (GPG_ERR_NOT_FOUND);
612       goto leave;
613     }
614
615   s = find_tlv (buffer, buflen, 0x71, &n);
616   if (!s || n != 1)
617     {
618       log_error ("piv: no or invalid CertInfo in 0x%X\n", tag);
619       err = gpg_error (GPG_ERR_INV_CERT_OBJ);
620       goto leave;
621     }
622   if (*s == 0x01)
623     {
624       log_error ("piv: gzip compression not yet supported (tag 0x%X)\n", tag);
625       err = gpg_error (GPG_ERR_UNSUPPORTED_ENCODING);
626       goto leave;
627     }
628   if (*s)
629     {
630       log_error ("piv: invalid CertInfo 0x%02x in 0x%X\n", *s, tag);
631       err = gpg_error (GPG_ERR_INV_CERT_OBJ);
632       goto leave;
633     }
634
635   /* Note: We don't check that the LRC octet has a length of zero as
636    * required by the specs.  */
637
638   /* Get the cert from the container.  */
639   s = find_tlv (buffer, buflen, 0x70, &n);
640   if (!s || !n)
641     {
642       err = gpg_error (GPG_ERR_NOT_FOUND);
643       goto leave;
644     }
645
646   if (!(*r_cert = xtrymalloc (n)))
647     {
648       err = gpg_error_from_syserror ();
649       goto leave;
650     }
651
652   memcpy (*r_cert, s, n);
653   *r_certlen = n;
654   err = 0;
655
656  leave:
657   xfree (relptr);
658   return err;
659 }
660
661
662 /* Get the keygrip of a key from the certificate stored at TAG.
663  * Caller must free the string at R_KEYGRIPSTR. */
664 static gpg_error_t
665 get_keygrip_by_tag (app_t app, unsigned int tag, char **r_keygripstr)
666 {
667   gpg_error_t err;
668   unsigned char *certbuf = NULL;
669   size_t certbuflen;
670   ksba_cert_t cert = NULL;
671
672   *r_keygripstr = xtrymalloc (40+1);
673   if (!r_keygripstr)
674     {
675       err = gpg_error_from_syserror ();
676       goto leave;
677     }
678
679   /* We need to get the public key from the certificate.  */
680   err = readcert_by_tag (app, tag, &certbuf, &certbuflen);
681   if (err)
682     goto leave;
683
684   /* Compute the keygrip.  */
685   err = ksba_cert_new (&cert);
686   if (err)
687     goto leave;
688   err = ksba_cert_init_from_mem (cert, certbuf, certbuflen);
689   if (err)
690     goto leave;
691   err = app_help_get_keygrip_string (cert, *r_keygripstr);
692
693
694  leave:
695   ksba_cert_release (cert);
696   xfree (certbuf);
697   if (err)
698     {
699       xfree (*r_keygripstr);
700       *r_keygripstr = NULL;
701     }
702   return err;
703 }
704
705
706 /* Locate the data object from the given KEYREF.  The KEYREF may also
707  * be the corresponding OID of the key object.  Returns the data
708  * object or NULL if not found.  */
709 static data_object_t
710 find_dobj_by_keyref (app_t app, const char *keyref)
711 {
712   int i;
713
714   (void)app;
715
716   if (!ascii_strncasecmp (keyref, "PIV.", 4))
717     {
718       keyref += 4;
719       for (i=0; data_objects[i].tag; i++)
720         if (*data_objects[i].keyref
721             && !ascii_strcasecmp (keyref, data_objects[i].keyref))
722           {
723             return data_objects + i;
724           }
725     }
726   else if (!strncmp (keyref, "2.16.840.1.101.3.7.", 19))
727     {
728       keyref += 19;
729       for (i=0; data_objects[i].tag; i++)
730         if (*data_objects[i].keyref
731             && !strcmp (keyref, data_objects[i].oidsuffix))
732           {
733             return data_objects + i;
734           }
735     }
736
737   return NULL;
738 }
739
740
741 /* Read a certificate from the card and returned in a freshly
742  * allocated buffer stored at R_CERT and the length of the certificate
743  * stored at R_CERTLEN.  CERTID is either the OID of the cert's
744  * container or of the form "PIV.<two_hexdigit_keyref>"  */
745 static gpg_error_t
746 do_readcert (app_t app, const char *certid,
747              unsigned char **r_cert, size_t *r_certlen)
748 {
749   data_object_t dobj;
750
751   *r_cert = NULL;
752   *r_certlen = 0;
753
754   dobj = find_dobj_by_keyref (app, certid);
755   if (!dobj)
756     return gpg_error (GPG_ERR_INV_ID);
757
758   return readcert_by_tag (app, dobj->tag, r_cert, r_certlen);
759 }
760
761
762 /* Given a data object DOBJ return the corresponding PIV algorithm and
763  * store it at R_ALGO.  The algorithm is taken from the corresponding
764  * certificate or from a cache.  */
765 static gpg_error_t
766 get_key_algorithm_by_dobj (app_t app, data_object_t dobj, int *r_algo)
767 {
768   gpg_error_t err;
769   unsigned char *certbuf = NULL;
770   size_t certbuflen;
771   ksba_cert_t cert = NULL;
772   ksba_sexp_t k_pkey = NULL;
773   gcry_sexp_t s_pkey = NULL;
774   gcry_sexp_t l1 = NULL;
775   char *algoname = NULL;
776   int algo;
777   size_t n;
778   const char *curve_name;
779
780   *r_algo = 0;
781
782   err = readcert_by_tag (app, dobj->tag, &certbuf, &certbuflen);
783   if (err)
784     goto leave;
785
786   err = ksba_cert_new (&cert);
787   if (err)
788     goto leave;
789
790   err = ksba_cert_init_from_mem (cert, certbuf, certbuflen);
791   if (err)
792     {
793       log_error ("piv: failed to parse the certificate %s: %s\n",
794                  dobj->keyref, gpg_strerror (err));
795       goto leave;
796     }
797   xfree (certbuf);
798   certbuf = NULL;
799
800   k_pkey = ksba_cert_get_public_key (cert);
801   if (!k_pkey)
802     {
803       err = gpg_error (GPG_ERR_NO_PUBKEY);
804       goto leave;
805     }
806   n = gcry_sexp_canon_len (k_pkey, 0, NULL, NULL);
807   err = gcry_sexp_new (&s_pkey, k_pkey, n, 0);
808   if (err)
809     goto leave;
810
811   l1 = gcry_sexp_find_token (s_pkey, "public-key", 0);
812   if (!l1)
813     {
814       err = gpg_error (GPG_ERR_NO_PUBKEY);
815       goto leave;
816     }
817
818   {
819     gcry_sexp_t l_tmp = gcry_sexp_cadr (l1);
820     gcry_sexp_release (l1);
821     l1 = l_tmp;
822   }
823   algoname = gcry_sexp_nth_string (l1, 0);
824   if (!algoname)
825     {
826       err = gpg_error_from_syserror ();
827       goto leave;
828     }
829
830   algo = gcry_pk_map_name (algoname);
831   switch (algo)
832     {
833     case GCRY_PK_RSA:
834       algo = PIV_ALGORITHM_RSA;
835       break;
836
837     case GCRY_PK_ECC:
838     case GCRY_PK_ECDSA:
839     case GCRY_PK_ECDH:
840       curve_name = gcry_pk_get_curve (s_pkey, 0, NULL);
841       if (curve_name && !strcmp (curve_name, "NIST P-256"))
842         algo = PIV_ALGORITHM_ECC_P256;
843       else if (curve_name && !strcmp (curve_name, "NIST P-384"))
844         algo = PIV_ALGORITHM_ECC_P384;
845       else
846         {
847           err = gpg_error (GPG_ERR_UNKNOWN_CURVE);
848           log_error ("piv: certificate %s, curve '%s': %s\n",
849                      dobj->keyref, curve_name, gpg_strerror (err));
850           goto leave;
851         }
852       break;
853
854     default:
855       err = gpg_error (GPG_ERR_PUBKEY_ALGO);
856       log_error ("piv: certificate %s, pubkey algo '%s': %s\n",
857                  dobj->keyref, algoname, gpg_strerror (err));
858       goto leave;
859     }
860   *r_algo = algo;
861
862  leave:
863   gcry_free (algoname);
864   gcry_sexp_release (l1);
865   gcry_sexp_release (s_pkey);
866   ksba_free (k_pkey);
867   xfree (certbuf);
868   return err;
869 }
870
871
872 /* Return an allocated string to be used as prompt.  Returns NULL on
873  * malloc error.  */
874 static char *
875 make_prompt (app_t app, int remaining, const char *firstline)
876 {
877   char *serial, *tmpbuf, *result;
878
879   serial = get_dispserialno (app, 0);
880   if (!serial)
881     return NULL;
882
883   /* TRANSLATORS: Put a \x1f right before a colon.  This can be
884    * used by pinentry to nicely align the names and values.  Keep
885    * the %s at the start and end of the string.  */
886   result = xtryasprintf (_("%s"
887                            "Number\x1f: %s%%0A"
888                            "Holder\x1f: %s"
889                            "%s"),
890                          "\x1e",
891                          serial,
892                          "Unknown", /* Fixme */
893                          "");
894   xfree (serial);
895
896   /* Append a "remaining attempts" info if needed.  */
897   if (remaining != -1 && remaining < 3)
898     {
899       char *rembuf;
900
901       /* TRANSLATORS: This is the number of remaining attempts to
902        * enter a PIN.  Use %%0A (double-percent,0A) for a linefeed. */
903       rembuf = xtryasprintf (_("Remaining attempts: %d"), remaining);
904       if (rembuf)
905         {
906           tmpbuf = strconcat (firstline, "%0A%0A", result,
907                               "%0A%0A", rembuf, NULL);
908           xfree (rembuf);
909         }
910       else
911         tmpbuf = NULL;
912       xfree (result);
913       result = tmpbuf;
914     }
915   else
916     {
917       tmpbuf = strconcat (firstline, "%0A%0A", result, NULL);
918       xfree (result);
919       result = tmpbuf;
920     }
921
922   return result;
923 }
924
925
926 /* Verify the Application PIN KEYREF.  */
927 static gpg_error_t
928 verify_pin (app_t app, int keyref,
929             gpg_error_t (*pincb)(void*,const char *,char **), void *pincb_arg)
930 {
931   gpg_error_t err;
932   unsigned char apdu[4];
933   unsigned int sw;
934   int remaining;
935   const char *label;
936   char *prompt;
937   char *pinvalue = NULL;
938   unsigned int pinlen;
939   char pinbuffer[8];
940   int minlen, maxlen, padding, onlydigits;
941
942   /* First check whether a verify is at all needed.  This is done with
943    * P1 being 0 and no Lc and command data send.  */
944   apdu[0] = 0x00;
945   apdu[1] = ISO7816_VERIFY;
946   apdu[2] = 0x00;
947   apdu[3] = keyref;
948   if (!iso7816_apdu_direct (app->slot, apdu, 4, 0, &sw, NULL, NULL))
949     {
950       /* No need to verification.  */
951       return 0;  /* All fine.  */
952     }
953   if ((sw & 0xfff0) == 0x63C0)
954     remaining = (sw & 0x000f); /* PIN has REMAINING tries left.  */
955   else
956     remaining = -1;
957
958   if (remaining != -1)
959     log_debug ("piv: PIN %2X has %d attempts left\n", keyref, remaining);
960
961   switch (keyref)
962     {
963     case 0x00:
964       minlen = 6;
965       maxlen = 8;
966       padding = 1;
967       onlydigits = 1;
968       label = _("||Please enter the Global-PIN of your PIV card");
969       break;
970     case 0x80:
971       minlen = 6;
972       maxlen = 8;
973       padding = 1;
974       onlydigits = 1;
975       label = _("||Please enter the PIN of your PIV card");
976       break;
977     case 0x81:
978       minlen = 8;
979       maxlen = 8;
980       padding = 0;
981       onlydigits = 0;
982       label = _("||Please enter the Unblocking Key of your PIV card");
983       break;
984
985     case 0x96:
986     case 0x97:
987     case 0x98:
988     case 0x9B:
989       return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
990
991     default:
992       return gpg_error (GPG_ERR_INV_ID);
993     }
994   log_assert (sizeof pinbuffer >= maxlen);
995
996
997   /* Ask for the PIN.  */
998   prompt = make_prompt (app, remaining, label);
999   err = pincb (pincb_arg, prompt, &pinvalue);
1000   xfree (prompt);
1001   prompt = NULL;
1002   if (err)
1003     {
1004       log_info (_("PIN callback returned error: %s\n"), gpg_strerror (err));
1005       return err;
1006     }
1007
1008   pinlen = pinvalue? strlen (pinvalue) : 0;
1009   if (pinlen < minlen)
1010     {
1011       log_error (_("PIN for is too short; minimum length is %d\n"), minlen);
1012       if (pinvalue)
1013         wipememory (pinvalue, pinlen);
1014       xfree (pinvalue);
1015       return gpg_error (GPG_ERR_BAD_PIN);
1016     }
1017   if (pinlen > maxlen)
1018     {
1019       log_error (_("PIN for is too long; maximum length is %d\n"), maxlen);
1020       wipememory (pinvalue, pinlen);
1021       xfree (pinvalue);
1022       return gpg_error (GPG_ERR_BAD_PIN);
1023     }
1024   if (onlydigits && strspn (pinvalue, "0123456789") != pinlen)
1025     {
1026       log_error (_("PIN has invalid characters; only digits are allowed\n"));
1027       wipememory (pinvalue, pinlen);
1028       xfree (pinvalue);
1029       return gpg_error (GPG_ERR_BAD_PIN);
1030     }
1031   memcpy (pinbuffer, pinvalue, pinlen);
1032   if (padding)
1033     {
1034       memset (pinbuffer + pinlen, 0xff, maxlen - pinlen);
1035       wipememory (pinvalue, pinlen);
1036       pinlen = maxlen;
1037     }
1038   else
1039     wipememory (pinvalue, pinlen);
1040   xfree (pinvalue);
1041
1042   err = iso7816_verify (app->slot, keyref, pinbuffer, pinlen);
1043   wipememory (pinbuffer, pinlen);
1044   if (err)
1045     log_error ("PIN %02X verification failed: %s\n", keyref,gpg_strerror (err));
1046
1047   return err;
1048 }
1049
1050
1051 /* Handle the PASSWD command.  Valid values for PWIDSTR are
1052  * key references related to PINs; in particular:
1053  *   PIV.00 - The Global PIN
1054  *   PIV.80 - The Application PIN
1055  *   PIV.81 - The PIN Unblocking key
1056  * The supported flags are:
1057  *   APP_CHANGE_FLAG_CLEAR   Clear the PIN verification state.
1058  */
1059 static gpg_error_t
1060 do_change_pin (app_t app, ctrl_t ctrl, const char *pwidstr,
1061                unsigned int flags,
1062                gpg_error_t (*pincb)(void*, const char *, char **),
1063                void *pincb_arg)
1064 {
1065   gpg_error_t err;
1066   int keyref;
1067   unsigned char apdu[4];
1068
1069   char *newpin = NULL;
1070   char *oldpin = NULL;
1071   size_t newpinlen;
1072   size_t oldpinlen;
1073   const char *newdesc;
1074   int pwid;
1075   pininfo_t pininfo;
1076
1077   (void)ctrl;
1078
1079   /* The minimum and maximum lengths are enforced by PIV.  */
1080   memset (&pininfo, 0, sizeof pininfo);
1081   pininfo.minlen = 6;
1082   pininfo.maxlen = 8;
1083
1084   keyref = parse_pin_keyref (pwidstr);
1085   if (keyref == -1)
1086     return gpg_error (GPG_ERR_INV_ID);
1087
1088   if ((flags & ~APP_CHANGE_FLAG_CLEAR))
1089     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
1090
1091   /* First see whether the special --clear mode has been requested.  */
1092   if ((flags & APP_CHANGE_FLAG_CLEAR))
1093     {
1094       apdu[0] = 0x00;
1095       apdu[1] = ISO7816_VERIFY;
1096       apdu[2] = 0xff;
1097       apdu[3] = keyref;
1098       err = iso7816_apdu_direct (app->slot, apdu, 4, 0, NULL, NULL, NULL);
1099       goto leave;
1100     }
1101
1102   err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1103
1104  leave:
1105   xfree (oldpin);
1106   xfree (newpin);
1107   return err;
1108 }
1109
1110
1111 /* Perform a simple verify operation for the PIN specified by PWIDSTR.
1112  * For valid values see do_change_pin.  */
1113 static gpg_error_t
1114 do_check_pin (app_t app, const char *pwidstr,
1115               gpg_error_t (*pincb)(void*, const char *, char **),
1116               void *pincb_arg)
1117 {
1118   int keyref;
1119
1120   keyref = parse_pin_keyref (pwidstr);
1121   if (keyref == -1)
1122     return gpg_error (GPG_ERR_INV_ID);
1123
1124   return verify_pin (app, keyref, pincb, pincb_arg);
1125 }
1126
1127
1128 /* Compute a digital signature using the GENERAL AUTHENTICATE command
1129  * on INDATA which is expected to be the raw message digest.  The
1130  * KEYIDSTR has the key reference or its OID (e.g. "PIV.9A").  The
1131  * result is stored at (R_OUTDATA,R_OUTDATALEN); on error (NULL,0) is
1132  * stored there and an error code returned.  For ECDSA the result is
1133  * the simple concatenation of R and S without any DER encoding.  R
1134  * and S are left extended with zeroes to make sure they have an equal
1135  * length.
1136  */
1137 static gpg_error_t
1138 do_auth (app_t app, const char *keyidstr,
1139          gpg_error_t (*pincb)(void*, const char *, char **),
1140          void *pincb_arg,
1141          const void *indata_arg, size_t indatalen,
1142          unsigned char **r_outdata, size_t *r_outdatalen)
1143 {
1144   const unsigned char *indata = indata_arg;
1145   gpg_error_t err;
1146   data_object_t dobj;
1147   unsigned char tmpl[2+2+2+128];
1148   size_t tmpllen;
1149   unsigned char *outdata = NULL;
1150   size_t outdatalen;
1151   const unsigned char *s;
1152   size_t n;
1153   int keyref, algo;
1154
1155   if (!keyidstr || !*keyidstr)
1156     {
1157       err = gpg_error (GPG_ERR_INV_VALUE);
1158       goto leave;
1159     }
1160
1161   /* Fixme: Shall we support the KEYID/FINGERPRINT syntax?  Does it
1162    * make sense for X.509 certs?  */
1163
1164   dobj = find_dobj_by_keyref (app, keyidstr);
1165   if (!dobj)
1166     {
1167       err = gpg_error (GPG_ERR_INV_ID);
1168       goto leave;
1169     }
1170   keyref = xtoi_2 (dobj->keyref);
1171
1172   err = get_key_algorithm_by_dobj (app, dobj, &algo);
1173   if (err)
1174     goto leave;
1175
1176   /* We need to remove the ASN.1 prefix from INDATA.  We use TEMPL as
1177    * a temporary buffer for the OID.  */
1178   if (algo == PIV_ALGORITHM_ECC_P256)
1179     {
1180       tmpllen = sizeof tmpl;
1181       err = gcry_md_get_asnoid (GCRY_MD_SHA256, &tmpl, &tmpllen);
1182       if (err)
1183         {
1184           err = gpg_error (GPG_ERR_INTERNAL);
1185           log_debug ("piv: no OID for hash algo %d\n", GCRY_MD_SHA256);
1186           goto leave;
1187         }
1188       if (indatalen != tmpllen + 32 || memcmp (indata, tmpl, tmpllen))
1189         {
1190           err = GPG_ERR_INV_VALUE;
1191           log_error ("piv: bad formatted input for ECC-P256 auth\n");
1192           goto leave;
1193         }
1194       indata +=tmpllen;
1195       indatalen -= tmpllen;
1196     }
1197   else if (algo == PIV_ALGORITHM_ECC_P384)
1198     {
1199       tmpllen = sizeof tmpl;
1200       err = gcry_md_get_asnoid (GCRY_MD_SHA384, &tmpl, &tmpllen);
1201       if (err)
1202         {
1203           err = gpg_error (GPG_ERR_INTERNAL);
1204           log_debug ("piv: no OID for hash algo %d\n", GCRY_MD_SHA384);
1205           goto leave;
1206         }
1207       if (indatalen != tmpllen + 48 || memcmp (indata, tmpl, tmpllen))
1208         {
1209           err = GPG_ERR_INV_VALUE;
1210           log_error ("piv: bad formatted input for ECC-P384 auth\n");
1211           goto leave;
1212         }
1213       indata += tmpllen;
1214       indatalen -= tmpllen;
1215     }
1216   else if (algo == PIV_ALGORITHM_RSA)
1217     {
1218       err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1219       log_error ("piv: FIXME: implement RSA authentication\n");
1220       goto leave;
1221     }
1222   else
1223     {
1224       err = gpg_error (GPG_ERR_INTERNAL);
1225       log_debug ("piv: unknown PIV  algo %d from helper function\n", algo);
1226       goto leave;
1227     }
1228
1229   /* Because we don't have a dynamic template builder we make sure
1230    * that we can encode all lengths in one octet.  FIXME: Use add_tls
1231    * from app-openpgp as a base for an strconcat like function. */
1232   if (indatalen >= 100)
1233     {
1234       err = gpg_error (GPG_ERR_TOO_LARGE);
1235       goto leave;
1236     }
1237
1238   /* Now verify the Application PIN.  */
1239   err = verify_pin (app, 0x80, pincb, pincb_arg);
1240   if (err)
1241     return err;
1242
1243   /* Build the Dynamic Authentication Template.  */
1244   tmpl[0] = 0x7c;
1245   tmpl[1] = indatalen + 4;
1246   tmpl[2] = 0x82; /* Response. */
1247   tmpl[3] = 0;    /* Must be 0 to get the tag in the answer.  */
1248   tmpl[4] = 0x81; /* Challenge. */
1249   tmpl[5] = indatalen;
1250   memcpy (tmpl+6, indata, indatalen);
1251   tmpllen = indatalen + 6;
1252
1253   /* Note: the -1 requests command chaining.  */
1254   err = iso7816_general_authenticate (app->slot, -1,
1255                                       algo, keyref,
1256                                       tmpl, (int)tmpllen, 0,
1257                                       &outdata, &outdatalen);
1258   if (err)
1259     goto leave;
1260
1261   /* Parse the response.  */
1262   if (outdatalen && *outdata == 0x7c
1263       && (s = find_tlv (outdata, outdatalen, 0x82, &n)))
1264     {
1265       const unsigned char *rval, *sval;
1266       size_t rlen, rlenx, slen, slenx, resultlen;
1267       char *result;
1268       /* The result of an ECDSA signature is
1269        *   SEQUENCE { r INTEGER, s INTEGER }
1270        * We re-pack that by concatenating R and S and making sure that
1271        * both have the same length.  We simplify parsing by using
1272        * find_tlv and not a proper DER parser.  */
1273       s = find_tlv (s, n, 0x30, &n);
1274       if (!s)
1275         goto bad_der;
1276       rval = find_tlv (s, n, 0x02, &rlen);
1277       if (!rval)
1278         goto bad_der;
1279       log_assert (n >= (rval-s)+rlen);
1280       sval = find_tlv (rval+rlen, n-((rval-s)+rlen), 0x02, &slen);
1281       if (!rval)
1282         goto bad_der;
1283       rlenx = slenx = 0;
1284       if (rlen > slen)
1285         slenx = rlen - slen;
1286       else if (slen > rlen)
1287         rlenx = slen - rlen;
1288
1289       resultlen = rlen + rlenx + slen + slenx;
1290       result = xtrycalloc (1, resultlen);
1291       if (!result)
1292         {
1293           err = gpg_error_from_syserror ();
1294           goto leave;
1295         }
1296       memcpy (result + rlenx, rval, rlen);
1297       memcpy (result + rlenx + rlen + slenx, sval, slen);
1298       xfree (outdata);
1299       outdata = result;
1300       outdatalen = resultlen;
1301     }
1302   else
1303     {
1304     bad_der:
1305       err = gpg_error (GPG_ERR_CARD);
1306       log_error ("piv: response does not contain a proper result\n");
1307       goto leave;
1308     }
1309
1310  leave:
1311   if (err)
1312     {
1313       xfree (outdata);
1314       *r_outdata = NULL;
1315       *r_outdatalen = 0;
1316     }
1317   else
1318     {
1319       *r_outdata = outdata;
1320       *r_outdatalen = outdatalen;
1321     }
1322   return err;
1323 }
1324
1325
1326 /* Select the PIV application on the card in SLOT.  This function must
1327  * be used before any other PIV application functions. */
1328 gpg_error_t
1329 app_select_piv (app_t app)
1330 {
1331   static char const aid[] = { 0xA0, 0x00, 0x00, 0x03, 0x08, /* RID=NIST */
1332                               0x00, 0x00, 0x10, 0x00        /* PIX=PIV  */ };
1333   int slot = app->slot;
1334   gpg_error_t err;
1335   unsigned char *apt = NULL;
1336   size_t aptlen;
1337   const unsigned char *s;
1338   size_t n;
1339
1340   /* Note that we select using the AID without the 2 octet version
1341    * number.  This allows for better reporting of future specs.  We
1342    * need to use the use-zero-for-P2-flag.  */
1343   err = iso7816_select_application_ext (slot, aid, sizeof aid, 0x0001,
1344                                         &apt, &aptlen);
1345   if (err)
1346     goto leave;
1347
1348   app->apptype = "PIV";
1349   app->did_chv1 = 0;
1350   app->did_chv2 = 0;
1351   app->did_chv3 = 0;
1352   app->app_local = NULL;
1353
1354   /* Check the Application Property Template.  */
1355   if (opt.verbose)
1356     {
1357       /* We  use a separate log_info to avoid the "DBG:" prefix.  */
1358       log_info ("piv: APT=");
1359       log_printhex (apt, aptlen, "");
1360     }
1361
1362   s = find_tlv (apt, aptlen, 0x4F, &n);
1363   if (!s || n != 6 || memcmp (s, aid+5, 4))
1364     {
1365       /* The PIX does not match.  */
1366       log_error ("piv: missing or invalid DO 0x4F in APT\n");
1367       err = gpg_error (GPG_ERR_CARD);
1368       goto leave;
1369     }
1370   if (s[4] != 1 || s[5] != 0)
1371     {
1372       log_error ("piv: unknown PIV version %u.%u\n", s[4], s[5]);
1373       err = gpg_error (GPG_ERR_CARD);
1374       goto leave;
1375     }
1376   app->card_version = ((s[4] << 8) | s[5]);
1377
1378   s = find_tlv (apt, aptlen, 0x79, &n);
1379   if (!s || n < 7)
1380     {
1381       log_error ("piv: missing or invalid DO 0x79 in APT\n");
1382       err = gpg_error (GPG_ERR_CARD);
1383       goto leave;
1384     }
1385   s = find_tlv (s, n, 0x4F, &n);
1386   if (!s || n != 5 || memcmp (s, aid, 5))
1387     {
1388       /* The RID does not match.  */
1389       log_error ("piv: missing or invalid DO 0x79.4F in APT\n");
1390       err = gpg_error (GPG_ERR_CARD);
1391       goto leave;
1392     }
1393
1394   app->app_local = xtrycalloc (1, sizeof *app->app_local);
1395   if (!app->app_local)
1396     {
1397       err = gpg_error_from_syserror ();
1398       goto leave;
1399     }
1400
1401
1402   /* FIXME: Parse the optional and conditional DOs in the APT.  */
1403
1404   if (opt.verbose)
1405     dump_all_do (slot);
1406
1407   app->fnc.deinit = do_deinit;
1408   app->fnc.learn_status = do_learn_status;
1409   app->fnc.readcert = do_readcert;
1410   app->fnc.readkey = NULL;
1411   app->fnc.getattr = do_getattr;
1412   /* app->fnc.setattr = do_setattr; */
1413   /* app->fnc.writecert = do_writecert; */
1414   /* app->fnc.writekey = do_writekey; */
1415   /* app->fnc.genkey = do_genkey; */
1416   /* app->fnc.sign = do_sign; */
1417   app->fnc.auth = do_auth;
1418   /* app->fnc.decipher = do_decipher; */
1419   app->fnc.change_pin = do_change_pin;
1420   app->fnc.check_pin = do_check_pin;
1421
1422
1423 leave:
1424   xfree (apt);
1425   if (err)
1426     do_deinit (app);
1427   return err;
1428 }