LCOV - code coverage report
Current view: top level - scd - app-dinsig.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 205 0.0 %
Date: 2016-09-12 12:29:17 Functions: 0 5 0.0 %

          Line data    Source code
       1             : /* app-dinsig.c - The DINSIG (DIN V 66291-1) card application.
       2             :  * Copyright (C) 2002, 2004, 2005, 2007, 2008 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 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 <http://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : 
      21             : /* The German signature law and its bylaw (SigG and SigV) is currently
      22             :    used with an interface specification described in DIN V 66291-1.
      23             :    The AID to be used is: 'D27600006601'.
      24             : 
      25             :    The file IDs for certificates utilize the generic format:
      26             :         Cxyz
      27             :     C being the hex digit 'C' (12).
      28             :     x being the service indicator:
      29             :          '0' := SigG conform digital signature.
      30             :          '1' := entity authentication.
      31             :          '2' := key encipherment.
      32             :          '3' := data encipherment.
      33             :          '4' := key agreement.
      34             :          other values are reserved for future use.
      35             :     y being the security environment number using '0' for cards
      36             :       not supporting a SE number.
      37             :     z being the certificate type:
      38             :          '0'        := C.CH (base certificate of card holder) or C.ICC.
      39             :          '1' .. '7' := C.CH (business or professional certificate
      40             :                        of card holder.
      41             :          '8' .. 'D' := C.CA (certificate of a CA issue by the Root-CA).
      42             :          'E'        := C.RCA (self certified certificate of the Root-CA).
      43             :          'F'        := reserved.
      44             : 
      45             :    The file IDs used by default are:
      46             :    '1F00'  EF.SSD (security service descriptor). [o,o]
      47             :    '2F02'  EF.GDO (global data objects) [m,m]
      48             :    'A000'  EF.PROT (signature log).  Cyclic file with 20 records of 53 byte.
      49             :            Read and update after user authentication. [o,o]
      50             :    'B000'  EF.PK.RCA.DS (public keys of Root-CA).  Size is 512b or size
      51             :            of keys. [m (unless a 'C00E' is present),m]
      52             :    'B001'  EF.PK.CA.DS (public keys of CAs).  Size is 512b or size
      53             :            of keys. [o,o]
      54             :    'C00n'  EF.C.CH.DS (digital signature certificate of card holder)
      55             :            with n := 0 .. 7.  Size is 2k or size of cert.  Read and
      56             :            update allowed after user authentication. [m,m]
      57             :    'C00m'  EF.C.CA.DS (digital signature certificate of CA)
      58             :            with m := 8 .. E.  Size is 1k or size of cert.  Read always
      59             :            allowed, update after user authentication. [o,o]
      60             :    'C100'  EF.C.ICC.AUT (AUT certificate of ICC) [o,m]
      61             :    'C108'  EF.C.CA.AUT (AUT certificate of CA) [o,m]
      62             :    'D000'  EF.DM (display message) [-,m]
      63             : 
      64             :    The letters in brackets indicate optional or mandatory files: The
      65             :    first for card terminals under full control and the second for
      66             :    "business" card terminals.
      67             : */
      68             : 
      69             : 
      70             : 
      71             : 
      72             : #include <config.h>
      73             : #include <errno.h>
      74             : #include <stdio.h>
      75             : #include <stdlib.h>
      76             : #include <string.h>
      77             : #include <assert.h>
      78             : #include <time.h>
      79             : 
      80             : #include "scdaemon.h"
      81             : 
      82             : #include "i18n.h"
      83             : #include "iso7816.h"
      84             : #include "app-common.h"
      85             : #include "tlv.h"
      86             : 
      87             : 
      88             : static gpg_error_t
      89           0 : do_learn_status (app_t app, ctrl_t ctrl, unsigned int flags)
      90             : {
      91             :   gpg_error_t err;
      92             :   char ct_buf[100], id_buf[100];
      93             :   char hexkeygrip[41];
      94             :   size_t len, certoff;
      95             :   unsigned char *der;
      96             :   size_t derlen;
      97             :   ksba_cert_t cert;
      98             :   int fid;
      99             : 
     100             :   (void)flags;
     101             : 
     102             :   /* Return the certificate of the card holder. */
     103           0 :   fid = 0xC000;
     104           0 :   len = app_help_read_length_of_cert (app->slot, fid, &certoff);
     105           0 :   if (!len)
     106           0 :     return 0; /* Card has not been personalized. */
     107             : 
     108           0 :   sprintf (ct_buf, "%d", 101);
     109           0 :   sprintf (id_buf, "DINSIG.%04X", fid);
     110           0 :   send_status_info (ctrl, "CERTINFO",
     111             :                     ct_buf, strlen (ct_buf),
     112             :                     id_buf, strlen (id_buf),
     113             :                     NULL, (size_t)0);
     114             : 
     115             :   /* Now we need to read the certificate, so that we can get the
     116             :      public key out of it.  */
     117           0 :   err = iso7816_read_binary (app->slot, certoff, len-certoff, &der, &derlen);
     118           0 :   if (err)
     119             :     {
     120           0 :       log_info ("error reading entire certificate from FID 0x%04X: %s\n",
     121             :                 fid, gpg_strerror (err));
     122           0 :       return 0;
     123             :     }
     124             : 
     125           0 :   err = ksba_cert_new (&cert);
     126           0 :   if (err)
     127             :     {
     128           0 :       xfree (der);
     129           0 :       return err;
     130             :     }
     131           0 :   err = ksba_cert_init_from_mem (cert, der, derlen);
     132           0 :   xfree (der); der = NULL;
     133           0 :   if (err)
     134             :     {
     135           0 :       log_error ("failed to parse the certificate at FID 0x%04X: %s\n",
     136             :                  fid, gpg_strerror (err));
     137           0 :       ksba_cert_release (cert);
     138           0 :       return err;
     139             :     }
     140           0 :   err = app_help_get_keygrip_string (cert, hexkeygrip);
     141           0 :   if (err)
     142             :     {
     143           0 :       log_error ("failed to calculate the keygrip for FID 0x%04X\n", fid);
     144           0 :       ksba_cert_release (cert);
     145           0 :       return gpg_error (GPG_ERR_CARD);
     146             :     }
     147           0 :   ksba_cert_release (cert);
     148             : 
     149           0 :   sprintf (id_buf, "DINSIG.%04X", fid);
     150           0 :   send_status_info (ctrl, "KEYPAIRINFO",
     151             :                     hexkeygrip, 40,
     152             :                     id_buf, strlen (id_buf),
     153             :                     NULL, (size_t)0);
     154           0 :   return 0;
     155             : }
     156             : 
     157             : 
     158             : 
     159             : 
     160             : /* Read the certificate with id CERTID (as returned by learn_status in
     161             :    the CERTINFO status lines) and return it in the freshly allocated
     162             :    buffer put into CERT and the length of the certificate put into
     163             :    CERTLEN.
     164             : 
     165             :    FIXME: This needs some cleanups and caching with do_learn_status.
     166             : */
     167             : static gpg_error_t
     168           0 : do_readcert (app_t app, const char *certid,
     169             :              unsigned char **cert, size_t *certlen)
     170             : {
     171             :   int fid;
     172             :   gpg_error_t err;
     173             :   unsigned char *buffer;
     174             :   const unsigned char *p;
     175             :   size_t buflen, n;
     176             :   int class, tag, constructed, ndef;
     177             :   size_t totobjlen, objlen, hdrlen;
     178           0 :   int rootca = 0;
     179             : 
     180           0 :   *cert = NULL;
     181           0 :   *certlen = 0;
     182           0 :   if (strncmp (certid, "DINSIG.", 7) )
     183           0 :     return gpg_error (GPG_ERR_INV_ID);
     184           0 :   certid += 7;
     185           0 :   if (!hexdigitp (certid) || !hexdigitp (certid+1)
     186           0 :       || !hexdigitp (certid+2) || !hexdigitp (certid+3)
     187           0 :       || certid[4])
     188           0 :     return gpg_error (GPG_ERR_INV_ID);
     189           0 :   fid = xtoi_4 (certid);
     190           0 :   if (fid != 0xC000 )
     191           0 :     return gpg_error (GPG_ERR_NOT_FOUND);
     192             : 
     193             :   /* Read the entire file.  fixme: This could be optimized by first
     194             :      reading the header to figure out how long the certificate
     195             :      actually is. */
     196           0 :   err = iso7816_select_file (app->slot, fid, 0, NULL, NULL);
     197           0 :   if (err)
     198             :     {
     199           0 :       log_error ("error selecting FID 0x%04X: %s\n", fid, gpg_strerror (err));
     200           0 :       return err;
     201             :     }
     202             : 
     203           0 :   err = iso7816_read_binary (app->slot, 0, 0, &buffer, &buflen);
     204           0 :   if (err)
     205             :     {
     206           0 :       log_error ("error reading certificate from FID 0x%04X: %s\n",
     207             :                  fid, gpg_strerror (err));
     208           0 :       return err;
     209             :     }
     210             : 
     211           0 :   if (!buflen || *buffer == 0xff)
     212             :     {
     213           0 :       log_info ("no certificate contained in FID 0x%04X\n", fid);
     214           0 :       err = gpg_error (GPG_ERR_NOT_FOUND);
     215           0 :       goto leave;
     216             :     }
     217             : 
     218             :   /* Now figure something out about the object. */
     219           0 :   p = buffer;
     220           0 :   n = buflen;
     221           0 :   err = parse_ber_header (&p, &n, &class, &tag, &constructed,
     222             :                           &ndef, &objlen, &hdrlen);
     223           0 :   if (err)
     224           0 :     goto leave;
     225           0 :   if ( class == CLASS_UNIVERSAL && tag == TAG_SEQUENCE && constructed )
     226             :     ;
     227           0 :   else if ( class == CLASS_UNIVERSAL && tag == TAG_SET && constructed )
     228           0 :     rootca = 1;
     229             :   else
     230           0 :     return gpg_error (GPG_ERR_INV_OBJ);
     231           0 :   totobjlen = objlen + hdrlen;
     232           0 :   assert (totobjlen <= buflen);
     233             : 
     234           0 :   err = parse_ber_header (&p, &n, &class, &tag, &constructed,
     235             :                           &ndef, &objlen, &hdrlen);
     236           0 :   if (err)
     237           0 :     goto leave;
     238             : 
     239           0 :   if (rootca)
     240             :     ;
     241           0 :   else if (class == CLASS_UNIVERSAL && tag == TAG_OBJECT_ID && !constructed)
     242             :     {
     243             :       const unsigned char *save_p;
     244             : 
     245             :       /* The certificate seems to be contained in a userCertificate
     246             :          container.  Skip this and assume the following sequence is
     247             :          the certificate. */
     248           0 :       if (n < objlen)
     249             :         {
     250           0 :           err = gpg_error (GPG_ERR_INV_OBJ);
     251           0 :           goto leave;
     252             :         }
     253           0 :       p += objlen;
     254           0 :       n -= objlen;
     255           0 :       save_p = p;
     256           0 :       err = parse_ber_header (&p, &n, &class, &tag, &constructed,
     257             :                               &ndef, &objlen, &hdrlen);
     258           0 :       if (err)
     259           0 :         goto leave;
     260           0 :       if ( !(class == CLASS_UNIVERSAL && tag == TAG_SEQUENCE && constructed) )
     261           0 :         return gpg_error (GPG_ERR_INV_OBJ);
     262           0 :       totobjlen = objlen + hdrlen;
     263           0 :       assert (save_p + totobjlen <= buffer + buflen);
     264           0 :       memmove (buffer, save_p, totobjlen);
     265             :     }
     266             : 
     267           0 :   *cert = buffer;
     268           0 :   buffer = NULL;
     269           0 :   *certlen = totobjlen;
     270             : 
     271             :  leave:
     272           0 :   xfree (buffer);
     273           0 :   return err;
     274             : }
     275             : 
     276             : 
     277             : /* Verify the PIN if required.  */
     278             : static gpg_error_t
     279           0 : verify_pin (app_t app,
     280             :             gpg_error_t (*pincb)(void*, const char *, char **),
     281             :             void *pincb_arg)
     282             : {
     283             :   const char *s;
     284             :   int rc;
     285             :   pininfo_t pininfo;
     286             : 
     287           0 :   if ( app->did_chv1 && !app->force_chv1 )
     288           0 :     return 0;  /* No need to verify it again.  */
     289             : 
     290           0 :   memset (&pininfo, 0, sizeof pininfo);
     291           0 :   pininfo.fixedlen = -1;
     292           0 :   pininfo.minlen = 6;
     293           0 :   pininfo.maxlen = 8;
     294             : 
     295           0 :   if (!opt.disable_pinpad
     296           0 :       && !iso7816_check_pinpad (app->slot, ISO7816_VERIFY, &pininfo) )
     297             :     {
     298           0 :       rc = pincb (pincb_arg,
     299           0 :                   _("||Please enter your PIN at the reader's pinpad"),
     300             :                   NULL);
     301           0 :       if (rc)
     302             :         {
     303           0 :           log_info (_("PIN callback returned error: %s\n"),
     304             :                     gpg_strerror (rc));
     305           0 :           return rc;
     306             :         }
     307           0 :       rc = iso7816_verify_kp (app->slot, 0x81, &pininfo);
     308             :       /* Dismiss the prompt. */
     309           0 :       pincb (pincb_arg, NULL, NULL);
     310             :     }
     311             :   else  /* No Pinpad.  */
     312             :     {
     313             :       char *pinvalue;
     314             : 
     315           0 :       rc = pincb (pincb_arg, "PIN", &pinvalue);
     316           0 :       if (rc)
     317             :         {
     318           0 :           log_info ("PIN callback returned error: %s\n", gpg_strerror (rc));
     319           0 :           return rc;
     320             :         }
     321             : 
     322             :       /* We require the PIN to be at least 6 and at max 8 bytes.
     323             :          According to the specs, this should all be ASCII.  */
     324           0 :       for (s=pinvalue; digitp (s); s++)
     325             :         ;
     326           0 :       if (*s)
     327             :         {
     328           0 :           log_error ("Non-numeric digits found in PIN\n");
     329           0 :           xfree (pinvalue);
     330           0 :           return gpg_error (GPG_ERR_BAD_PIN);
     331             :         }
     332             : 
     333           0 :       if (strlen (pinvalue) < pininfo.minlen)
     334             :         {
     335           0 :           log_error ("PIN is too short; minimum length is %d\n",
     336             :                      pininfo.minlen);
     337           0 :           xfree (pinvalue);
     338           0 :           return gpg_error (GPG_ERR_BAD_PIN);
     339             :         }
     340           0 :       else if (strlen (pinvalue) > pininfo.maxlen)
     341             :         {
     342           0 :           log_error ("PIN is too large; maximum length is %d\n",
     343             :                      pininfo.maxlen);
     344           0 :           xfree (pinvalue);
     345           0 :           return gpg_error (GPG_ERR_BAD_PIN);
     346             :         }
     347             : 
     348           0 :       rc = iso7816_verify (app->slot, 0x81, pinvalue, strlen (pinvalue));
     349           0 :       if (gpg_err_code (rc) == GPG_ERR_INV_VALUE)
     350             :         {
     351             :           /* We assume that ISO 9564-1 encoding is used and we failed
     352             :              because the first nibble we passed was 3 and not 2.  DIN
     353             :              says something about looking up such an encoding in the
     354             :              SSD but I was not able to find any tag relevant to
     355             :              this. */
     356             :           char paddedpin[8];
     357             :           int i, ndigits;
     358             : 
     359           0 :           for (ndigits=0, s=pinvalue; *s; ndigits++, s++)
     360             :             ;
     361           0 :           i = 0;
     362           0 :           paddedpin[i++] = 0x20 | (ndigits & 0x0f);
     363           0 :           for (s=pinvalue; i < sizeof paddedpin && *s && s[1]; s = s+2 )
     364           0 :             paddedpin[i++] = (((*s - '0') << 4) | ((s[1] - '0') & 0x0f));
     365           0 :           if (i < sizeof paddedpin && *s)
     366           0 :             paddedpin[i++] = (((*s - '0') << 4) | 0x0f);
     367           0 :           while (i < sizeof paddedpin)
     368           0 :             paddedpin[i++] = 0xff;
     369           0 :           rc = iso7816_verify (app->slot, 0x81, paddedpin, sizeof paddedpin);
     370             :         }
     371           0 :       xfree (pinvalue);
     372             :     }
     373             : 
     374           0 :   if (rc)
     375             :     {
     376           0 :       log_error ("verify PIN failed\n");
     377           0 :       return rc;
     378             :     }
     379           0 :   app->did_chv1 = 1;
     380           0 :   return 0;
     381             : }
     382             : 
     383             : 
     384             : 
     385             : /* Create the signature and return the allocated result in OUTDATA.
     386             :    If a PIN is required the PINCB will be used to ask for the PIN;
     387             :    that callback should return the PIN in an allocated buffer and
     388             :    store that in the 3rd argument.  */
     389             : static gpg_error_t
     390           0 : do_sign (app_t app, const char *keyidstr, int hashalgo,
     391             :          gpg_error_t (*pincb)(void*, const char *, char **),
     392             :          void *pincb_arg,
     393             :          const void *indata, size_t indatalen,
     394             :          unsigned char **outdata, size_t *outdatalen )
     395             : {
     396             :   static unsigned char sha1_prefix[15] = /* Object ID is 1.3.14.3.2.26 */
     397             :     { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
     398             :       0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 };
     399             :   static unsigned char rmd160_prefix[15] = /* Object ID is 1.3.36.3.2.1 */
     400             :     { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03,
     401             :       0x02, 0x01, 0x05, 0x00, 0x04, 0x14 };
     402             :   static unsigned char sha256_prefix[19] = /* OID is 2.16.840.1.101.3.4.2.1 */
     403             :     { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
     404             :       0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
     405             :       0x00, 0x04, 0x20 };
     406             :   int rc;
     407             :   int fid;
     408             :   unsigned char data[19+32]; /* Must be large enough for a SHA-256 digest
     409             :                                 + the largest OID _prefix above. */
     410             :   int datalen;
     411             : 
     412           0 :   if (!keyidstr || !*keyidstr)
     413           0 :     return gpg_error (GPG_ERR_INV_VALUE);
     414           0 :   if (indatalen != 20 && indatalen != 16 && indatalen != 32
     415           0 :       && indatalen != (15+20) && indatalen != (19+32))
     416           0 :     return gpg_error (GPG_ERR_INV_VALUE);
     417             : 
     418             :   /* Check that the provided ID is vaid.  This is not really needed
     419             :      but we do it to to enforce correct usage by the caller. */
     420           0 :   if (strncmp (keyidstr, "DINSIG.", 7) )
     421           0 :     return gpg_error (GPG_ERR_INV_ID);
     422           0 :   keyidstr += 7;
     423           0 :   if (!hexdigitp (keyidstr) || !hexdigitp (keyidstr+1)
     424           0 :       || !hexdigitp (keyidstr+2) || !hexdigitp (keyidstr+3)
     425           0 :       || keyidstr[4])
     426           0 :     return gpg_error (GPG_ERR_INV_ID);
     427           0 :   fid = xtoi_4 (keyidstr);
     428           0 :   if (fid != 0xC000)
     429           0 :     return gpg_error (GPG_ERR_NOT_FOUND);
     430             : 
     431             :   /* Prepare the DER object from INDATA. */
     432           0 :   datalen = 35;
     433           0 :   if (indatalen == 15+20)
     434             :     {
     435             :       /* Alright, the caller was so kind to send us an already
     436             :          prepared DER object.  Check that it is what we want and that
     437             :          it matches the hash algorithm. */
     438           0 :       if (hashalgo == GCRY_MD_SHA1 && !memcmp (indata, sha1_prefix, 15))
     439             :         ;
     440           0 :       else if (hashalgo == GCRY_MD_RMD160 && !memcmp (indata, rmd160_prefix,15))
     441             :         ;
     442             :       else
     443           0 :         return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
     444           0 :       memcpy (data, indata, indatalen);
     445             :     }
     446           0 :   else if (indatalen == 19+32)
     447             :     {
     448             :       /* Alright, the caller was so kind to send us an already
     449             :          prepared DER object.  Check that it is what we want and that
     450             :          it matches the hash algorithm. */
     451           0 :       datalen = indatalen;
     452           0 :       if (hashalgo == GCRY_MD_SHA256 && !memcmp (indata, sha256_prefix, 19))
     453             :         ;
     454           0 :       else if (hashalgo == GCRY_MD_SHA1 && !memcmp (indata, sha256_prefix, 19))
     455             :         {
     456             :           /* Fixme: This is a kludge.  A better solution is not to use
     457             :              SHA1 as default but use an autodetection.  However this
     458             :              needs changes in all app-*.c */
     459           0 :           hashalgo = GCRY_MD_SHA256;
     460           0 :           datalen  = indatalen;
     461             :         }
     462             :       else
     463           0 :         return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
     464           0 :       memcpy (data, indata, indatalen);
     465             :     }
     466             :   else
     467             :     {
     468           0 :       int len = 15;
     469           0 :       if (hashalgo == GCRY_MD_SHA1)
     470           0 :         memcpy (data, sha1_prefix, len);
     471           0 :       else if (hashalgo == GCRY_MD_RMD160)
     472           0 :         memcpy (data, rmd160_prefix, len);
     473           0 :       else if (hashalgo == GCRY_MD_SHA256)
     474             :         {
     475           0 :           len = 19;
     476           0 :           datalen = len + indatalen;
     477           0 :           memcpy (data, sha256_prefix, len);
     478             :         }
     479             :       else
     480           0 :         return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
     481           0 :       memcpy (data+len, indata, indatalen);
     482             :     }
     483             : 
     484           0 :   rc = verify_pin (app, pincb, pincb_arg);
     485           0 :   if (!rc)
     486           0 :     rc = iso7816_compute_ds (app->slot, 0, data, datalen, 0,
     487             :                              outdata, outdatalen);
     488           0 :   return rc;
     489             : }
     490             : 
     491             : 
     492             : #if 0
     493             : #warning test function - works but may brick your card
     494             : /* Handle the PASSWD command.  CHVNOSTR is currently ignored; we
     495             :    always use VHV0.  RESET_MODE is not yet implemented.  */
     496             : static gpg_error_t
     497             : do_change_pin (app_t app, ctrl_t ctrl,  const char *chvnostr,
     498             :                unsigned int flags,
     499             :                gpg_error_t (*pincb)(void*, const char *, char **),
     500             :                void *pincb_arg)
     501             : {
     502             :   gpg_error_t err;
     503             :   char *pinvalue;
     504             :   const char *oldpin;
     505             :   size_t oldpinlen;
     506             : 
     507             :   if ((flags & APP_CHANGE_FLAG_RESET))
     508             :     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
     509             : 
     510             :   if ((flags & APP_CHANGE_FLAG_NULLPIN))
     511             :     {
     512             :       /* With the nullpin flag, we do not verify the PIN - it would fail
     513             :          if the Nullpin is still set.  */
     514             :       oldpin = "\0\0\0\0\0";
     515             :       oldpinlen = 6;
     516             :     }
     517             :   else
     518             :     {
     519             :       err = verify_pin (app, pincb, pincb_arg);
     520             :       if (err)
     521             :         return err;
     522             :       oldpin = NULL;
     523             :       oldpinlen = 0;
     524             :     }
     525             : 
     526             :   /* TRANSLATORS: Do not translate the "|*|" prefixes but
     527             :      keep it at the start of the string.  We need this elsewhere
     528             :      to get some infos on the string. */
     529             :   err = pincb (pincb_arg, _("|N|Initial New PIN"), &pinvalue);
     530             :   if (err)
     531             :     {
     532             :       log_error (_("error getting new PIN: %s\n"), gpg_strerror (err));
     533             :       return err;
     534             :     }
     535             : 
     536             :   err = iso7816_change_reference_data (app->slot, 0x81,
     537             :                                        oldpin, oldpinlen,
     538             :                                        pinvalue, strlen (pinvalue));
     539             :   xfree (pinvalue);
     540             :   return err;
     541             : }
     542             : #endif /*0*/
     543             : 
     544             : 
     545             : /* Select the DINSIG application on the card in SLOT.  This function
     546             :    must be used before any other DINSIG application functions. */
     547             : gpg_error_t
     548           0 : app_select_dinsig (app_t app)
     549             : {
     550             :   static char const aid[] = { 0xD2, 0x76, 0x00, 0x00, 0x66, 0x01 };
     551           0 :   int slot = app->slot;
     552             :   int rc;
     553             : 
     554           0 :   rc = iso7816_select_application (slot, aid, sizeof aid, 0);
     555           0 :   if (!rc)
     556             :     {
     557           0 :       app->apptype = "DINSIG";
     558             : 
     559           0 :       app->fnc.learn_status = do_learn_status;
     560           0 :       app->fnc.readcert = do_readcert;
     561           0 :       app->fnc.getattr = NULL;
     562           0 :       app->fnc.setattr = NULL;
     563           0 :       app->fnc.genkey = NULL;
     564           0 :       app->fnc.sign = do_sign;
     565           0 :       app->fnc.auth = NULL;
     566           0 :       app->fnc.decipher = NULL;
     567           0 :       app->fnc.change_pin = NULL /*do_change_pin*/;
     568           0 :       app->fnc.check_pin = NULL;
     569             : 
     570           0 :       app->force_chv1 = 1;
     571             :    }
     572             : 
     573           0 :   return rc;
     574             : }

Generated by: LCOV version 1.11