LCOV - code coverage report
Current view: top level - scd - app-nks.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 574 0.0 %
Date: 2016-11-29 15:00:56 Functions: 0 20 0.0 %

          Line data    Source code
       1             : /* app-nks.c - The Telesec NKS card application.
       2             :  * Copyright (C) 2004, 2007, 2008, 2009 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 <https://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : /* Notes:
      21             : 
      22             :   - We are now targeting TCOS 3 cards and it may happen that there is
      23             :     a regression towards TCOS 2 cards.  Please report.
      24             : 
      25             :   - The TKS3 AUT key is not used.  It seems that it is only useful for
      26             :     the internal authentication command and not accessible by other
      27             :     applications.  The key itself is in the encryption class but the
      28             :     corresponding certificate has only the digitalSignature
      29             :     capability.
      30             : 
      31             :   - If required, we automagically switch between the NKS application
      32             :     and the SigG application.  This avoids to use the DINSIG
      33             :     application which is somewhat limited, has no support for Secure
      34             :     Messaging as required by TCOS 3 and has no way to change the PIN
      35             :     or even set the NullPIN.
      36             : 
      37             :   - We use the prefix NKS-DF01 for TCOS 2 cards and NKS-NKS3 for newer
      38             :     cards.  This is because the NKS application has moved to DF02 with
      39             :     TCOS 3 and thus we better use a DF independent tag.
      40             : 
      41             :   - We use only the global PINs for the NKS application.
      42             : 
      43             :  */
      44             : 
      45             : #include <config.h>
      46             : #include <errno.h>
      47             : #include <stdio.h>
      48             : #include <stdlib.h>
      49             : #include <string.h>
      50             : #include <assert.h>
      51             : #include <time.h>
      52             : 
      53             : #include "scdaemon.h"
      54             : #include "i18n.h"
      55             : #include "iso7816.h"
      56             : #include "app-common.h"
      57             : #include "tlv.h"
      58             : #include "apdu.h"
      59             : #include "host2net.h"
      60             : 
      61             : static char const aid_nks[]  = { 0xD2, 0x76, 0x00, 0x00, 0x03, 0x01, 0x02 };
      62             : static char const aid_sigg[] = { 0xD2, 0x76, 0x00, 0x00, 0x66, 0x01 };
      63             : 
      64             : 
      65             : static struct
      66             : {
      67             :   int is_sigg;   /* Valid for SigG application.  */
      68             :   int fid;       /* File ID. */
      69             :   int nks_ver;   /* 0 for NKS version 2, 3 for version 3. */
      70             :   int certtype;  /* Type of certificate or 0 if it is not a certificate. */
      71             :   int iskeypair; /* If true has the FID of the corresponding certificate. */
      72             :   int issignkey; /* True if file is a key usable for signing. */
      73             :   int isenckey;  /* True if file is a key usable for decryption. */
      74             :   unsigned char kid;  /* Corresponding key references.  */
      75             : } filelist[] = {
      76             :   { 0, 0x4531, 0, 0,  0xC000, 1, 0, 0x80 }, /* EF_PK.NKS.SIG */
      77             :   { 0, 0xC000, 0, 101 },                    /* EF_C.NKS.SIG  */
      78             :   { 0, 0x4331, 0, 100 },
      79             :   { 0, 0x4332, 0, 100 },
      80             :   { 0, 0xB000, 0, 110 },                    /* EF_PK.RCA.NKS */
      81             :   { 0, 0x45B1, 0, 0,  0xC200, 0, 1, 0x81 }, /* EF_PK.NKS.ENC */
      82             :   { 0, 0xC200, 0, 101 },                    /* EF_C.NKS.ENC  */
      83             :   { 0, 0x43B1, 0, 100 },
      84             :   { 0, 0x43B2, 0, 100 },
      85             : /* The authentication key is not used.  */
      86             : /*   { 0, 0x4571, 3, 0,  0xC500, 0, 0, 0x82 }, /\* EF_PK.NKS.AUT *\/ */
      87             : /*   { 0, 0xC500, 3, 101 },                    /\* EF_C.NKS.AUT  *\/ */
      88             :   { 0, 0x45B2, 3, 0,  0xC201, 0, 1, 0x83 }, /* EF_PK.NKS.ENC1024 */
      89             :   { 0, 0xC201, 3, 101 },                    /* EF_C.NKS.ENC1024  */
      90             :   { 1, 0x4531, 3, 0,  0xC000, 1, 1, 0x84 }, /* EF_PK.CH.SIG  */
      91             :   { 1, 0xC000, 0, 101 },                    /* EF_C.CH.SIG  */
      92             :   { 1, 0xC008, 3, 101 },                    /* EF_C.CA.SIG  */
      93             :   { 1, 0xC00E, 3, 111 },                    /* EF_C.RCA.SIG  */
      94             :   { 0, 0 }
      95             : };
      96             : 
      97             : 
      98             : 
      99             : /* Object with application (i.e. NKS) specific data.  */
     100             : struct app_local_s {
     101             :   int nks_version;  /* NKS version.  */
     102             : 
     103             :   int sigg_active;  /* True if switched to the SigG application.  */
     104             :   int sigg_msig_checked;/*  True if we checked for a mass signature card.  */
     105             :   int sigg_is_msig; /* True if this is a mass signature card.  */
     106             : 
     107             :   int need_app_select; /* Need to re-select the application.  */
     108             : 
     109             : };
     110             : 
     111             : 
     112             : 
     113             : static gpg_error_t switch_application (app_t app, int enable_sigg);
     114             : 
     115             : 
     116             : 
     117             : /* Release local data. */
     118             : static void
     119           0 : do_deinit (app_t app)
     120             : {
     121           0 :   if (app && app->app_local)
     122             :     {
     123           0 :       xfree (app->app_local);
     124           0 :       app->app_local = NULL;
     125             :     }
     126           0 : }
     127             : 
     128             : 
     129             : static int
     130           0 : all_zero_p (void *buffer, size_t length)
     131             : {
     132             :   char *p;
     133             : 
     134           0 :   for (p=buffer; length; length--, p++)
     135           0 :     if (*p)
     136           0 :       return 0;
     137           0 :   return 1;
     138             : }
     139             : 
     140             : 
     141             : /* Read the file with FID, assume it contains a public key and return
     142             :    its keygrip in the caller provided 41 byte buffer R_GRIPSTR. */
     143             : static gpg_error_t
     144           0 : keygripstr_from_pk_file (app_t app, int fid, char *r_gripstr)
     145             : {
     146             :   gpg_error_t err;
     147             :   unsigned char grip[20];
     148             :   unsigned char *buffer[2];
     149             :   size_t buflen[2];
     150             :   gcry_sexp_t sexp;
     151             :   int i;
     152           0 :   int offset[2] = { 0, 0 };
     153             : 
     154           0 :   err = iso7816_select_file (app->slot, fid, 0, NULL, NULL);
     155           0 :   if (err)
     156           0 :     return err;
     157           0 :   err = iso7816_read_record (app->slot, 1, 1, 0, &buffer[0], &buflen[0]);
     158           0 :   if (err)
     159           0 :     return err;
     160           0 :   err = iso7816_read_record (app->slot, 2, 1, 0, &buffer[1], &buflen[1]);
     161           0 :   if (err)
     162             :     {
     163           0 :       xfree (buffer[0]);
     164           0 :       return err;
     165             :     }
     166             : 
     167           0 :   if (app->app_local->nks_version < 3)
     168             :     {
     169             :       /* Old versions of NKS store the values in a TLV encoded format.
     170             :          We need to do some checks.  */
     171           0 :       for (i=0; i < 2; i++)
     172             :         {
     173             :           /* Check that the value appears like an integer encoded as
     174             :              Simple-TLV.  We don't check the tag because the tests cards I
     175             :              have use 1 for both, the modulus and the exponent - the
     176             :              example in the documentation gives 2 for the exponent. */
     177           0 :           if (buflen[i] < 3)
     178           0 :             err = gpg_error (GPG_ERR_TOO_SHORT);
     179           0 :           else if (buffer[i][1] != buflen[i]-2 )
     180           0 :             err = gpg_error (GPG_ERR_INV_OBJ);
     181             :           else
     182           0 :             offset[i] = 2;
     183             :         }
     184             :     }
     185             :   else
     186             :     {
     187             :       /* Remove leading zeroes to get a correct keygrip.  Take care of
     188             :          negative numbers.  We should also fix it the same way in
     189             :          libgcrypt but we can't yet rely on it yet.  */
     190           0 :       for (i=0; i < 2; i++)
     191             :         {
     192           0 :           while (buflen[i]-offset[i] > 1
     193           0 :                  && !buffer[i][offset[i]]
     194           0 :                  && !(buffer[i][offset[i]+1] & 0x80))
     195           0 :             offset[i]++;
     196             :         }
     197             :     }
     198             : 
     199             :   /* Check whether negative values are not prefixed with a zero and
     200             :      fix that.  */
     201           0 :   for (i=0; i < 2; i++)
     202             :     {
     203           0 :       if ((buflen[i]-offset[i]) && (buffer[i][offset[i]] & 0x80))
     204             :         {
     205             :           unsigned char *newbuf;
     206             :           size_t newlen;
     207             : 
     208           0 :           newlen = 1 + buflen[i] - offset[i];
     209           0 :           newbuf = xtrymalloc (newlen);
     210           0 :           if (!newlen)
     211             :             {
     212           0 :               xfree (buffer[0]);
     213           0 :               xfree (buffer[1]);
     214           0 :               return gpg_error_from_syserror ();
     215             :             }
     216           0 :           newbuf[0] = 0;
     217           0 :           memcpy (newbuf+1, buffer[i]+offset[i], buflen[i] - offset[i]);
     218           0 :           xfree (buffer[i]);
     219           0 :           buffer[i] = newbuf;
     220           0 :           buflen[i] = newlen;
     221           0 :           offset[i] = 0;
     222             :         }
     223             :     }
     224             : 
     225           0 :   if (!err)
     226           0 :     err = gcry_sexp_build (&sexp, NULL,
     227             :                            "(public-key (rsa (n %b) (e %b)))",
     228           0 :                            (int)buflen[0]-offset[0], buffer[0]+offset[0],
     229           0 :                            (int)buflen[1]-offset[1], buffer[1]+offset[1]);
     230             : 
     231           0 :   xfree (buffer[0]);
     232           0 :   xfree (buffer[1]);
     233           0 :   if (err)
     234           0 :     return err;
     235             : 
     236           0 :   if (!gcry_pk_get_keygrip (sexp, grip))
     237             :     {
     238           0 :       err = gpg_error (GPG_ERR_INTERNAL); /* i.e. RSA not supported by
     239             :                                              libgcrypt. */
     240             :     }
     241             :   else
     242             :     {
     243           0 :       bin2hex (grip, 20, r_gripstr);
     244             :     }
     245           0 :   gcry_sexp_release (sexp);
     246           0 :   return err;
     247             : }
     248             : 
     249             : 
     250             : /* TCOS responds to a verify with empty data (i.e. without the Lc
     251             :    byte) with the status of the PIN.  PWID is the PIN ID, If SIGG is
     252             :    true, the application is switched into SigG mode.
     253             :    Returns:
     254             :             -1 = Error retrieving the data,
     255             :             -2 = No such PIN,
     256             :             -3 = PIN blocked,
     257             :             -4 = NullPIN activ,
     258             :         n >= 0 = Number of verification attempts left.  */
     259             : static int
     260           0 : get_chv_status (app_t app, int sigg, int pwid)
     261             : {
     262           0 :   unsigned char *result = NULL;
     263             :   size_t resultlen;
     264             :   char command[4];
     265             :   int rc;
     266             : 
     267           0 :   if (switch_application (app, sigg))
     268           0 :     return sigg? -2 : -1; /* No such PIN / General error.  */
     269             : 
     270           0 :   command[0] = 0x00;
     271           0 :   command[1] = 0x20;
     272           0 :   command[2] = 0x00;
     273           0 :   command[3] = pwid;
     274             : 
     275           0 :   if (apdu_send_direct (app->slot, 0, (unsigned char *)command,
     276             :                         4, 0, &result, &resultlen))
     277           0 :     rc = -1; /* Error. */
     278           0 :   else if (resultlen < 2)
     279           0 :     rc = -1; /* Error. */
     280             :   else
     281             :     {
     282           0 :       unsigned int sw = buf16_to_uint (result+resultlen-2);
     283             : 
     284           0 :       if (sw == 0x6a88)
     285           0 :         rc = -2; /* No such PIN.  */
     286           0 :       else if (sw == 0x6983)
     287           0 :         rc = -3; /* PIN is blocked.  */
     288           0 :       else if (sw == 0x6985)
     289           0 :         rc = -4; /* NullPIN is activ.  */
     290           0 :       else if ((sw & 0xfff0) == 0x63C0)
     291           0 :         rc = (sw & 0x000f); /* PIN has N tries left.  */
     292             :       else
     293           0 :         rc = -1; /* Other error.  */
     294             :     }
     295           0 :   xfree (result);
     296             : 
     297           0 :   return rc;
     298             : }
     299             : 
     300             : 
     301             : /* Implement the GETATTR command.  This is similar to the LEARN
     302             :    command but returns just one value via the status interface. */
     303             : static gpg_error_t
     304           0 : do_getattr (app_t app, ctrl_t ctrl, const char *name)
     305             : {
     306             :   static struct {
     307             :     const char *name;
     308             :     int special;
     309             :   } table[] = {
     310             :     { "$AUTHKEYID",   1 },
     311             :     { "NKS-VERSION",  2 },
     312             :     { "CHV-STATUS",   3 },
     313             :     { NULL, 0 }
     314             :   };
     315           0 :   gpg_error_t err = 0;
     316             :   int idx;
     317             :   char buffer[100];
     318             : 
     319           0 :   err = switch_application (app, 0);
     320           0 :   if (err)
     321           0 :     return err;
     322             : 
     323           0 :   for (idx=0; table[idx].name && strcmp (table[idx].name, name); idx++)
     324             :     ;
     325           0 :   if (!table[idx].name)
     326           0 :     return gpg_error (GPG_ERR_INV_NAME);
     327             : 
     328           0 :   switch (table[idx].special)
     329             :     {
     330             :     case 1: /* $AUTHKEYID */
     331             :       {
     332             :         /* NetKey 3.0 cards define an authentication key but according
     333             :            to the specs this key is only usable for encryption and not
     334             :            signing.  it might work anyway but it has not yet been
     335             :            tested - fixme.  Thus for now we use the NKS signature key
     336             :            for authentication.  */
     337           0 :         char const tmp[] = "NKS-NKS3.4531";
     338           0 :         send_status_info (ctrl, table[idx].name, tmp, strlen (tmp), NULL, 0);
     339             :       }
     340           0 :       break;
     341             : 
     342             :     case 2: /* NKS-VERSION */
     343           0 :       snprintf (buffer, sizeof buffer, "%d", app->app_local->nks_version);
     344           0 :       send_status_info (ctrl, table[idx].name,
     345             :                         buffer, strlen (buffer), NULL, 0);
     346           0 :       break;
     347             : 
     348             :     case 3: /* CHV-STATUS */
     349             :       {
     350             :         /* Returns: PW1.CH PW2.CH PW1.CH.SIG PW2.CH.SIG That are the
     351             :            two global passwords followed by the two SigG passwords.
     352             :            For the values, see the function get_chv_status.  */
     353             :         int tmp[4];
     354             : 
     355             :         /* We use a helper array so that we can control that there is
     356             :            no superfluous application switch.  Note that PW2.CH.SIG
     357             :            really has the identifier 0x83 and not 0x82 as one would
     358             :            expect.  */
     359           0 :         tmp[0] = get_chv_status (app, 0, 0x00);
     360           0 :         tmp[1] = get_chv_status (app, 0, 0x01);
     361           0 :         tmp[2] = get_chv_status (app, 1, 0x81);
     362           0 :         tmp[3] = get_chv_status (app, 1, 0x83);
     363           0 :         snprintf (buffer, sizeof buffer,
     364             :                   "%d %d %d %d", tmp[0], tmp[1], tmp[2], tmp[3]);
     365           0 :         send_status_info (ctrl, table[idx].name,
     366             :                           buffer, strlen (buffer), NULL, 0);
     367             :       }
     368           0 :       break;
     369             : 
     370             : 
     371             :     default:
     372           0 :       err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
     373           0 :       break;
     374             :     }
     375             : 
     376           0 :   return err;
     377             : }
     378             : 
     379             : 
     380             : 
     381             : static void
     382           0 : do_learn_status_core (app_t app, ctrl_t ctrl, unsigned int flags, int is_sigg)
     383             : {
     384             :   gpg_error_t err;
     385             :   char ct_buf[100], id_buf[100];
     386             :   int i;
     387             :   const char *tag;
     388             : 
     389           0 :   if (is_sigg)
     390           0 :     tag = "SIGG";
     391           0 :   else if (app->app_local->nks_version < 3)
     392           0 :     tag = "DF01";
     393             :   else
     394           0 :     tag = "NKS3";
     395             : 
     396             :   /* Output information about all useful objects in the NKS application. */
     397           0 :   for (i=0; filelist[i].fid; i++)
     398             :     {
     399           0 :       if (filelist[i].nks_ver > app->app_local->nks_version)
     400           0 :         continue;
     401             : 
     402           0 :       if (!!filelist[i].is_sigg != !!is_sigg)
     403           0 :         continue;
     404             : 
     405           0 :       if (filelist[i].certtype && !(flags &1))
     406           0 :         {
     407             :           size_t len;
     408             : 
     409           0 :           len = app_help_read_length_of_cert (app->slot,
     410             :                                               filelist[i].fid, NULL);
     411           0 :           if (len)
     412             :             {
     413             :               /* FIXME: We should store the length in the application's
     414             :                  context so that a following readcert does only need to
     415             :                  read that many bytes. */
     416           0 :               snprintf (ct_buf, sizeof ct_buf, "%d", filelist[i].certtype);
     417           0 :               snprintf (id_buf, sizeof id_buf, "NKS-%s.%04X",
     418             :                         tag, filelist[i].fid);
     419           0 :               send_status_info (ctrl, "CERTINFO",
     420             :                                 ct_buf, strlen (ct_buf),
     421             :                                 id_buf, strlen (id_buf),
     422             :                                 NULL, (size_t)0);
     423             :             }
     424             :         }
     425           0 :       else if (filelist[i].iskeypair)
     426             :         {
     427             :           char gripstr[40+1];
     428             : 
     429           0 :           err = keygripstr_from_pk_file (app, filelist[i].fid, gripstr);
     430           0 :           if (err)
     431           0 :             log_error ("can't get keygrip from FID 0x%04X: %s\n",
     432             :                        filelist[i].fid, gpg_strerror (err));
     433             :           else
     434             :             {
     435           0 :               snprintf (id_buf, sizeof id_buf, "NKS-%s.%04X",
     436             :                         tag, filelist[i].fid);
     437           0 :               send_status_info (ctrl, "KEYPAIRINFO",
     438             :                                 gripstr, 40,
     439             :                                 id_buf, strlen (id_buf),
     440             :                                 NULL, (size_t)0);
     441             :             }
     442             :         }
     443             :     }
     444             : 
     445             : 
     446           0 : }
     447             : 
     448             : 
     449             : static gpg_error_t
     450           0 : do_learn_status (app_t app, ctrl_t ctrl, unsigned int flags)
     451             : {
     452             :   gpg_error_t err;
     453             : 
     454           0 :   err = switch_application (app, 0);
     455           0 :   if (err)
     456           0 :     return err;
     457             : 
     458           0 :   do_learn_status_core (app, ctrl, flags, 0);
     459             : 
     460           0 :   err = switch_application (app, 1);
     461           0 :   if (err)
     462           0 :     return 0;  /* Silently ignore if we can't switch to SigG.  */
     463             : 
     464           0 :   do_learn_status_core (app, ctrl, flags, 1);
     465             : 
     466           0 :   return 0;
     467             : }
     468             : 
     469             : 
     470             : 
     471             : 
     472             : /* Read the certificate with id CERTID (as returned by learn_status in
     473             :    the CERTINFO status lines) and return it in the freshly allocated
     474             :    buffer put into CERT and the length of the certificate put into
     475             :    CERTLEN. */
     476             : static gpg_error_t
     477           0 : do_readcert (app_t app, const char *certid,
     478             :              unsigned char **cert, size_t *certlen)
     479             : {
     480             :   int i, fid;
     481             :   gpg_error_t err;
     482             :   unsigned char *buffer;
     483             :   const unsigned char *p;
     484             :   size_t buflen, n;
     485             :   int class, tag, constructed, ndef;
     486             :   size_t totobjlen, objlen, hdrlen;
     487           0 :   int rootca = 0;
     488           0 :   int is_sigg = 0;
     489             : 
     490           0 :   *cert = NULL;
     491           0 :   *certlen = 0;
     492             : 
     493           0 :   if (!strncmp (certid, "NKS-NKS3.", 9))
     494             :     ;
     495           0 :   else if (!strncmp (certid, "NKS-DF01.", 9))
     496             :     ;
     497           0 :   else if (!strncmp (certid, "NKS-SIGG.", 9))
     498           0 :     is_sigg = 1;
     499             :   else
     500           0 :     return gpg_error (GPG_ERR_INV_ID);
     501             : 
     502           0 :   err = switch_application (app, is_sigg);
     503           0 :   if (err)
     504           0 :     return err;
     505             : 
     506           0 :   certid += 9;
     507           0 :   if (!hexdigitp (certid) || !hexdigitp (certid+1)
     508           0 :       || !hexdigitp (certid+2) || !hexdigitp (certid+3)
     509           0 :       || certid[4])
     510           0 :     return gpg_error (GPG_ERR_INV_ID);
     511           0 :   fid = xtoi_4 (certid);
     512           0 :   for (i=0; filelist[i].fid; i++)
     513           0 :     if ((filelist[i].certtype || filelist[i].iskeypair)
     514           0 :         && filelist[i].fid == fid)
     515           0 :       break;
     516           0 :   if (!filelist[i].fid)
     517           0 :     return gpg_error (GPG_ERR_NOT_FOUND);
     518             : 
     519             :   /* If the requested objects is a plain public key, redirect it to
     520             :      the corresponding certificate.  The whole system is a bit messy
     521             :      because we sometime use the key directly or let the caller
     522             :      retrieve the key from the certificate.  The rationale for
     523             :      that is to support not-yet stored certificates. */
     524           0 :   if (filelist[i].iskeypair)
     525           0 :     fid = filelist[i].iskeypair;
     526             : 
     527             : 
     528             :   /* Read the entire file.  fixme: This could be optimized by first
     529             :      reading the header to figure out how long the certificate
     530             :      actually is. */
     531           0 :   err = iso7816_select_file (app->slot, fid, 0, NULL, NULL);
     532           0 :   if (err)
     533             :     {
     534           0 :       log_error ("error selecting FID 0x%04X: %s\n", fid, gpg_strerror (err));
     535           0 :       return err;
     536             :     }
     537             : 
     538           0 :   err = iso7816_read_binary (app->slot, 0, 0, &buffer, &buflen);
     539           0 :   if (err)
     540             :     {
     541           0 :       log_error ("error reading certificate from FID 0x%04X: %s\n",
     542             :                  fid, gpg_strerror (err));
     543           0 :       return err;
     544             :     }
     545             : 
     546           0 :   if (!buflen || *buffer == 0xff)
     547             :     {
     548           0 :       log_info ("no certificate contained in FID 0x%04X\n", fid);
     549           0 :       err = gpg_error (GPG_ERR_NOT_FOUND);
     550           0 :       goto leave;
     551             :     }
     552             : 
     553             :   /* Now figure something out about the object. */
     554           0 :   p = buffer;
     555           0 :   n = buflen;
     556           0 :   err = parse_ber_header (&p, &n, &class, &tag, &constructed,
     557             :                           &ndef, &objlen, &hdrlen);
     558           0 :   if (err)
     559           0 :     goto leave;
     560           0 :   if ( class == CLASS_UNIVERSAL && tag == TAG_SEQUENCE && constructed )
     561             :     ;
     562           0 :   else if ( class == CLASS_UNIVERSAL && tag == TAG_SET && constructed )
     563           0 :     rootca = 1;
     564             :   else
     565           0 :     return gpg_error (GPG_ERR_INV_OBJ);
     566           0 :   totobjlen = objlen + hdrlen;
     567           0 :   assert (totobjlen <= buflen);
     568             : 
     569           0 :   err = parse_ber_header (&p, &n, &class, &tag, &constructed,
     570             :                           &ndef, &objlen, &hdrlen);
     571           0 :   if (err)
     572           0 :     goto leave;
     573             : 
     574           0 :   if (rootca)
     575             :     ;
     576           0 :   else if (class == CLASS_UNIVERSAL && tag == TAG_OBJECT_ID && !constructed)
     577             :     {
     578             :       const unsigned char *save_p;
     579             : 
     580             :       /* The certificate seems to be contained in a userCertificate
     581             :          container.  Skip this and assume the following sequence is
     582             :          the certificate. */
     583           0 :       if (n < objlen)
     584             :         {
     585           0 :           err = gpg_error (GPG_ERR_INV_OBJ);
     586           0 :           goto leave;
     587             :         }
     588           0 :       p += objlen;
     589           0 :       n -= objlen;
     590           0 :       save_p = p;
     591           0 :       err = parse_ber_header (&p, &n, &class, &tag, &constructed,
     592             :                               &ndef, &objlen, &hdrlen);
     593           0 :       if (err)
     594           0 :         goto leave;
     595           0 :       if ( !(class == CLASS_UNIVERSAL && tag == TAG_SEQUENCE && constructed) )
     596           0 :         return gpg_error (GPG_ERR_INV_OBJ);
     597           0 :       totobjlen = objlen + hdrlen;
     598           0 :       assert (save_p + totobjlen <= buffer + buflen);
     599           0 :       memmove (buffer, save_p, totobjlen);
     600             :     }
     601             : 
     602           0 :   *cert = buffer;
     603           0 :   buffer = NULL;
     604           0 :   *certlen = totobjlen;
     605             : 
     606             :  leave:
     607           0 :   xfree (buffer);
     608           0 :   return err;
     609             : }
     610             : 
     611             : 
     612             : /* Handle the READKEY command. On success a canonical encoded
     613             :    S-expression with the public key will get stored at PK and its
     614             :    length at PKLEN; the caller must release that buffer.  On error PK
     615             :    and PKLEN are not changed and an error code is returned.  As of now
     616             :    this function is only useful for the internal authentication key.
     617             :    Other keys are automagically retrieved via by means of the
     618             :    certificate parsing code in commands.c:cmd_readkey.  For internal
     619             :    use PK and PKLEN may be NULL to just check for an existing key.  */
     620             : static gpg_error_t
     621           0 : do_readkey (app_t app, int advanced, const char *keyid,
     622             :             unsigned char **pk, size_t *pklen)
     623             : {
     624             :   gpg_error_t err;
     625             :   unsigned char *buffer[2];
     626             :   size_t buflen[2];
     627           0 :   unsigned short path[1] = { 0x4500 };
     628             : 
     629           0 :   if (advanced)
     630           0 :     return GPG_ERR_NOT_SUPPORTED;
     631             : 
     632             :   /* We use a generic name to retrieve PK.AUT.IFD-SPK.  */
     633           0 :   if (!strcmp (keyid, "$IFDAUTHKEY") && app->app_local->nks_version >= 3)
     634             :     ;
     635             :   else /* Return the error code expected by cmd_readkey.  */
     636           0 :     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
     637             : 
     638             :   /* Access the KEYD file which is always in the master directory.  */
     639           0 :   err = iso7816_select_path (app->slot, path, DIM (path), NULL, NULL);
     640           0 :   if (err)
     641           0 :     return err;
     642             :   /* Due to the above select we need to re-select our application.  */
     643           0 :   app->app_local->need_app_select = 1;
     644             :   /* Get the two records.  */
     645           0 :   err = iso7816_read_record (app->slot, 5, 1, 0, &buffer[0], &buflen[0]);
     646           0 :   if (err)
     647           0 :     return err;
     648           0 :   if (all_zero_p (buffer[0], buflen[0]))
     649             :     {
     650           0 :       xfree (buffer[0]);
     651           0 :       return gpg_error (GPG_ERR_NOT_FOUND);
     652             :     }
     653           0 :   err = iso7816_read_record (app->slot, 6, 1, 0, &buffer[1], &buflen[1]);
     654           0 :   if (err)
     655             :     {
     656           0 :       xfree (buffer[0]);
     657           0 :       return err;
     658             :     }
     659             : 
     660           0 :   if (pk && pklen)
     661             :     {
     662           0 :       *pk = make_canon_sexp_from_rsa_pk (buffer[0], buflen[0],
     663           0 :                                          buffer[1], buflen[1],
     664             :                                          pklen);
     665           0 :       if (!*pk)
     666           0 :         err = gpg_error_from_syserror ();
     667             :     }
     668             : 
     669           0 :   xfree (buffer[0]);
     670           0 :   xfree (buffer[1]);
     671           0 :   return err;
     672             : }
     673             : 
     674             : 
     675             : /* Handle the WRITEKEY command for NKS.  This function expects a
     676             :    canonical encoded S-expression with the public key in KEYDATA and
     677             :    its length in KEYDATALEN.  The only supported KEYID is
     678             :    "$IFDAUTHKEY" to store the terminal key on the card.  Bit 0 of
     679             :    FLAGS indicates whether an existing key shall get overwritten.
     680             :    PINCB and PINCB_ARG are the usual arguments for the pinentry
     681             :    callback.  */
     682             : static gpg_error_t
     683           0 : do_writekey (app_t app, ctrl_t ctrl,
     684             :              const char *keyid, unsigned int flags,
     685             :              gpg_error_t (*pincb)(void*, const char *, char **),
     686             :              void *pincb_arg,
     687             :              const unsigned char *keydata, size_t keydatalen)
     688             : {
     689             :   gpg_error_t err;
     690           0 :   int force = (flags & 1);
     691           0 :   const unsigned char *rsa_n = NULL;
     692           0 :   const unsigned char *rsa_e = NULL;
     693             :   size_t rsa_n_len, rsa_e_len;
     694             :   unsigned int nbits;
     695             : 
     696             :   (void)ctrl;
     697             :   (void)pincb;
     698             :   (void)pincb_arg;
     699             : 
     700           0 :   if (!strcmp (keyid, "$IFDAUTHKEY") && app->app_local->nks_version >= 3)
     701             :     ;
     702             :   else
     703           0 :     return gpg_error (GPG_ERR_INV_ID);
     704             : 
     705           0 :   if (!force && !do_readkey (app, 0, keyid, NULL, NULL))
     706           0 :     return gpg_error (GPG_ERR_EEXIST);
     707             : 
     708             :   /* Parse the S-expression.  */
     709           0 :   err = get_rsa_pk_from_canon_sexp (keydata, keydatalen,
     710             :                                     &rsa_n, &rsa_n_len, &rsa_e, &rsa_e_len);
     711           0 :   if (err)
     712           0 :     goto leave;
     713             : 
     714             :   /* Check that the parameters match the requirements.  */
     715           0 :   nbits = app_help_count_bits (rsa_n, rsa_n_len);
     716           0 :   if (nbits != 1024)
     717             :     {
     718           0 :       log_error (_("RSA modulus missing or not of size %d bits\n"), 1024);
     719           0 :       err = gpg_error (GPG_ERR_BAD_PUBKEY);
     720           0 :       goto leave;
     721             :     }
     722             : 
     723           0 :   nbits = app_help_count_bits (rsa_e, rsa_e_len);
     724           0 :   if (nbits < 2 || nbits > 32)
     725             :     {
     726           0 :       log_error (_("RSA public exponent missing or larger than %d bits\n"),
     727             :                  32);
     728           0 :       err = gpg_error (GPG_ERR_BAD_PUBKEY);
     729           0 :       goto leave;
     730             :     }
     731             : 
     732             : /*   /\* Store them.  *\/ */
     733             : /*   err = verify_pin (app, 0, NULL, pincb, pincb_arg); */
     734             : /*   if (err) */
     735             : /*     goto leave; */
     736             : 
     737             :   /* Send the MSE:Store_Public_Key.  */
     738           0 :   err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
     739             : /*   mse = xtrymalloc (1000); */
     740             : 
     741             : /*   mse[0] = 0x80; /\* Algorithm reference.  *\/ */
     742             : /*   mse[1] = 1; */
     743             : /*   mse[2] = 0x17; */
     744             : /*   mse[3] = 0x84; /\* Private key reference.  *\/ */
     745             : /*   mse[4] = 1; */
     746             : /*   mse[5] = 0x77; */
     747             : /*   mse[6] = 0x7F; /\* Public key parameter.  *\/ */
     748             : /*   mse[7] = 0x49; */
     749             : /*   mse[8] = 0x81; */
     750             : /*   mse[9] = 3 + 0x80 + 2 + rsa_e_len; */
     751             : /*   mse[10] = 0x81; /\* RSA modulus of 128 byte.  *\/ */
     752             : /*   mse[11] = 0x81; */
     753             : /*   mse[12] = rsa_n_len; */
     754             : /*   memcpy (mse+12, rsa_n, rsa_n_len); */
     755             : /*   mse[10] = 0x82; /\* RSA public exponent of up to 4 bytes.  *\/ */
     756             : /*   mse[12] = rsa_e_len; */
     757             : /*   memcpy (mse+12, rsa_e, rsa_e_len); */
     758             : /*   err = iso7816_manage_security_env (app->slot, 0x81, 0xB6, */
     759             : /*                                      mse, sizeof mse); */
     760             : 
     761             :  leave:
     762           0 :   return err;
     763             : }
     764             : 
     765             : 
     766             : static gpg_error_t
     767           0 : basic_pin_checks (const char *pinvalue, int minlen, int maxlen)
     768             : {
     769           0 :   if (strlen (pinvalue) < minlen)
     770             :     {
     771           0 :       log_error ("PIN is too short; minimum length is %d\n", minlen);
     772           0 :       return gpg_error (GPG_ERR_BAD_PIN);
     773             :     }
     774           0 :   if (strlen (pinvalue) > maxlen)
     775             :     {
     776           0 :       log_error ("PIN is too large; maximum length is %d\n", maxlen);
     777           0 :       return gpg_error (GPG_ERR_BAD_PIN);
     778             :     }
     779           0 :   return 0;
     780             : }
     781             : 
     782             : 
     783             : /* Verify the PIN if required.  */
     784             : static gpg_error_t
     785           0 : verify_pin (app_t app, int pwid, const char *desc,
     786             :             gpg_error_t (*pincb)(void*, const char *, char **),
     787             :             void *pincb_arg)
     788             : {
     789             :   pininfo_t pininfo;
     790             :   int rc;
     791             : 
     792           0 :   if (!desc)
     793           0 :     desc = "PIN";
     794             : 
     795           0 :   memset (&pininfo, 0, sizeof pininfo);
     796           0 :   pininfo.fixedlen = -1;
     797           0 :   pininfo.minlen = 6;
     798           0 :   pininfo.maxlen = 16;
     799             : 
     800           0 :   if (!opt.disable_pinpad
     801           0 :       && !iso7816_check_pinpad (app->slot, ISO7816_VERIFY, &pininfo) )
     802             :     {
     803           0 :       rc = pincb (pincb_arg, desc, NULL);
     804           0 :       if (rc)
     805             :         {
     806           0 :           log_info (_("PIN callback returned error: %s\n"),
     807             :                     gpg_strerror (rc));
     808           0 :           return rc;
     809             :         }
     810             : 
     811           0 :       rc = iso7816_verify_kp (app->slot, pwid, &pininfo);
     812           0 :       pincb (pincb_arg, NULL, NULL);  /* Dismiss the prompt. */
     813             :     }
     814             :   else
     815             :     {
     816             :       char *pinvalue;
     817             : 
     818           0 :       rc = pincb (pincb_arg, desc, &pinvalue);
     819           0 :       if (rc)
     820             :         {
     821           0 :           log_info ("PIN callback returned error: %s\n", gpg_strerror (rc));
     822           0 :           return rc;
     823             :         }
     824             : 
     825           0 :       rc = basic_pin_checks (pinvalue, pininfo.minlen, pininfo.maxlen);
     826           0 :       if (rc)
     827             :         {
     828           0 :           xfree (pinvalue);
     829           0 :           return rc;
     830             :         }
     831             : 
     832           0 :       rc = iso7816_verify (app->slot, pwid, pinvalue, strlen (pinvalue));
     833           0 :       xfree (pinvalue);
     834             :     }
     835             : 
     836           0 :   if (rc)
     837             :     {
     838           0 :       if ( gpg_err_code (rc) == GPG_ERR_USE_CONDITIONS )
     839           0 :         log_error (_("the NullPIN has not yet been changed\n"));
     840             :       else
     841           0 :         log_error ("verify PIN failed\n");
     842           0 :       return rc;
     843             :     }
     844             : 
     845           0 :   return 0;
     846             : }
     847             : 
     848             : 
     849             : /* Create the signature and return the allocated result in OUTDATA.
     850             :    If a PIN is required the PINCB will be used to ask for the PIN;
     851             :    that callback should return the PIN in an allocated buffer and
     852             :    store that in the 3rd argument.  */
     853             : static gpg_error_t
     854           0 : do_sign (app_t app, const char *keyidstr, int hashalgo,
     855             :          gpg_error_t (*pincb)(void*, const char *, char **),
     856             :          void *pincb_arg,
     857             :          const void *indata, size_t indatalen,
     858             :          unsigned char **outdata, size_t *outdatalen )
     859             : {
     860             :   static unsigned char sha1_prefix[15] = /* Object ID is 1.3.14.3.2.26 */
     861             :     { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
     862             :       0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 };
     863             :   static unsigned char rmd160_prefix[15] = /* Object ID is 1.3.36.3.2.1 */
     864             :     { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03,
     865             :       0x02, 0x01, 0x05, 0x00, 0x04, 0x14 };
     866             :   int rc, i;
     867           0 :   int is_sigg = 0;
     868             :   int fid;
     869             :   unsigned char kid;
     870             :   unsigned char data[83];   /* Must be large enough for a SHA-1 digest
     871             :                                + the largest OID prefix. */
     872             :   size_t datalen;
     873             : 
     874           0 :   if (!keyidstr || !*keyidstr)
     875           0 :     return gpg_error (GPG_ERR_INV_VALUE);
     876           0 :   switch (indatalen)
     877             :     {
     878           0 :     case 16: case 20: case 35: case 47: case 51: case 67: case 83: break;
     879           0 :     default: return gpg_error (GPG_ERR_INV_VALUE);
     880             :     }
     881             : 
     882             :   /* Check that the provided ID is valid.  This is not really needed
     883             :      but we do it to enforce correct usage by the caller. */
     884           0 :   if (!strncmp (keyidstr, "NKS-NKS3.", 9) )
     885             :     ;
     886           0 :   else if (!strncmp (keyidstr, "NKS-DF01.", 9) )
     887             :     ;
     888           0 :   else if (!strncmp (keyidstr, "NKS-SIGG.", 9) )
     889           0 :     is_sigg = 1;
     890             :   else
     891           0 :     return gpg_error (GPG_ERR_INV_ID);
     892           0 :   keyidstr += 9;
     893             : 
     894           0 :   rc = switch_application (app, is_sigg);
     895           0 :   if (rc)
     896           0 :     return rc;
     897             : 
     898           0 :   if (is_sigg && app->app_local->sigg_is_msig)
     899             :     {
     900           0 :       log_info ("mass signature cards are not allowed\n");
     901           0 :       return gpg_error (GPG_ERR_NOT_SUPPORTED);
     902             :     }
     903             : 
     904           0 :   if (!hexdigitp (keyidstr) || !hexdigitp (keyidstr+1)
     905           0 :       || !hexdigitp (keyidstr+2) || !hexdigitp (keyidstr+3)
     906           0 :       || keyidstr[4])
     907           0 :     return gpg_error (GPG_ERR_INV_ID);
     908           0 :   fid = xtoi_4 (keyidstr);
     909           0 :   for (i=0; filelist[i].fid; i++)
     910           0 :     if (filelist[i].iskeypair && filelist[i].fid == fid)
     911           0 :       break;
     912           0 :   if (!filelist[i].fid)
     913           0 :     return gpg_error (GPG_ERR_NOT_FOUND);
     914           0 :   if (!filelist[i].issignkey)
     915           0 :     return gpg_error (GPG_ERR_INV_ID);
     916           0 :   kid = filelist[i].kid;
     917             : 
     918             :   /* Prepare the DER object from INDATA.  */
     919           0 :   if (app->app_local->nks_version > 2 && (indatalen == 35
     920           0 :                                           || indatalen == 47
     921           0 :                                           || indatalen == 51
     922           0 :                                           || indatalen == 67
     923           0 :                                           || indatalen == 83))
     924             :     {
     925             :       /* The caller send data matching the length of the ASN.1 encoded
     926             :          hash for SHA-{1,224,256,384,512}.  Assume that is okay.  */
     927           0 :       assert (indatalen <= sizeof data);
     928           0 :       memcpy (data, indata, indatalen);
     929           0 :       datalen = indatalen;
     930             :     }
     931           0 :   else if (indatalen == 35)
     932             :     {
     933             :       /* Alright, the caller was so kind to send us an already
     934             :          prepared DER object.  This is for TCOS 2. */
     935           0 :       if (hashalgo == GCRY_MD_SHA1 && !memcmp (indata, sha1_prefix, 15))
     936             :         ;
     937           0 :       else if (hashalgo == GCRY_MD_RMD160 && !memcmp (indata,rmd160_prefix,15))
     938             :         ;
     939             :       else
     940           0 :         return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
     941           0 :       memcpy (data, indata, indatalen);
     942           0 :       datalen = 35;
     943             :     }
     944           0 :   else if (indatalen == 20)
     945             :     {
     946           0 :       if (hashalgo == GCRY_MD_SHA1)
     947           0 :         memcpy (data, sha1_prefix, 15);
     948           0 :       else if (hashalgo == GCRY_MD_RMD160)
     949           0 :         memcpy (data, rmd160_prefix, 15);
     950             :       else
     951           0 :         return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
     952           0 :       memcpy (data+15, indata, indatalen);
     953           0 :       datalen = 35;
     954             :     }
     955             :   else
     956           0 :     return gpg_error (GPG_ERR_INV_VALUE);
     957             : 
     958             : 
     959             :   /* Send an MSE for PSO:Computer_Signature.  */
     960           0 :   if (app->app_local->nks_version > 2)
     961             :     {
     962             :       unsigned char mse[6];
     963             : 
     964           0 :       mse[0] = 0x80; /* Algorithm reference.  */
     965           0 :       mse[1] = 1;
     966           0 :       mse[2] = 2;    /* RSA, card does pkcs#1 v1.5 padding, no ASN.1 check.  */
     967           0 :       mse[3] = 0x84; /* Private key reference.  */
     968           0 :       mse[4] = 1;
     969           0 :       mse[5] = kid;
     970           0 :       rc = iso7816_manage_security_env (app->slot, 0x41, 0xB6,
     971             :                                         mse, sizeof mse);
     972             :     }
     973             :   /* Verify using PW1.CH.  */
     974           0 :   if (!rc)
     975           0 :     rc = verify_pin (app, 0, NULL, pincb, pincb_arg);
     976             :   /* Compute the signature.  */
     977           0 :   if (!rc)
     978           0 :     rc = iso7816_compute_ds (app->slot, 0, data, datalen, 0,
     979             :                              outdata, outdatalen);
     980           0 :   return rc;
     981             : }
     982             : 
     983             : 
     984             : 
     985             : /* Decrypt the data in INDATA and return the allocated result in OUTDATA.
     986             :    If a PIN is required the PINCB will be used to ask for the PIN; it
     987             :    should return the PIN in an allocated buffer and put it into PIN.  */
     988             : static gpg_error_t
     989           0 : do_decipher (app_t app, const char *keyidstr,
     990             :              gpg_error_t (*pincb)(void*, const char *, char **),
     991             :              void *pincb_arg,
     992             :              const void *indata, size_t indatalen,
     993             :              unsigned char **outdata, size_t *outdatalen,
     994             :              unsigned int *r_info)
     995             : {
     996             :   int rc, i;
     997           0 :   int is_sigg = 0;
     998             :   int fid;
     999             :   int kid;
    1000             : 
    1001             :   (void)r_info;
    1002             : 
    1003           0 :   if (!keyidstr || !*keyidstr || !indatalen)
    1004           0 :     return gpg_error (GPG_ERR_INV_VALUE);
    1005             : 
    1006             :   /* Check that the provided ID is valid.  This is not really needed
    1007             :      but we do it to to enforce correct usage by the caller. */
    1008           0 :   if (!strncmp (keyidstr, "NKS-NKS3.", 9) )
    1009             :     ;
    1010           0 :   else if (!strncmp (keyidstr, "NKS-DF01.", 9) )
    1011             :     ;
    1012           0 :   else if (!strncmp (keyidstr, "NKS-SIGG.", 9) )
    1013           0 :     is_sigg = 1;
    1014             :   else
    1015           0 :     return gpg_error (GPG_ERR_INV_ID);
    1016           0 :   keyidstr += 9;
    1017             : 
    1018           0 :   rc = switch_application (app, is_sigg);
    1019           0 :   if (rc)
    1020           0 :     return rc;
    1021             : 
    1022           0 :   if (!hexdigitp (keyidstr) || !hexdigitp (keyidstr+1)
    1023           0 :       || !hexdigitp (keyidstr+2) || !hexdigitp (keyidstr+3)
    1024           0 :       || keyidstr[4])
    1025           0 :     return gpg_error (GPG_ERR_INV_ID);
    1026           0 :   fid = xtoi_4 (keyidstr);
    1027           0 :   for (i=0; filelist[i].fid; i++)
    1028           0 :     if (filelist[i].iskeypair && filelist[i].fid == fid)
    1029           0 :       break;
    1030           0 :   if (!filelist[i].fid)
    1031           0 :     return gpg_error (GPG_ERR_NOT_FOUND);
    1032           0 :   if (!filelist[i].isenckey)
    1033           0 :     return gpg_error (GPG_ERR_INV_ID);
    1034           0 :   kid = filelist[i].kid;
    1035             : 
    1036           0 :   if (app->app_local->nks_version > 2)
    1037             :     {
    1038             :       unsigned char mse[6];
    1039           0 :       mse[0] = 0x80; /* Algorithm reference.  */
    1040           0 :       mse[1] = 1;
    1041           0 :       mse[2] = 0x0a; /* RSA no padding.  (0x1A is pkcs#1.5 padding.)  */
    1042           0 :       mse[3] = 0x84; /* Private key reference.  */
    1043           0 :       mse[4] = 1;
    1044           0 :       mse[5] = kid;
    1045           0 :       rc = iso7816_manage_security_env (app->slot, 0x41, 0xB8,
    1046             :                                         mse, sizeof mse);
    1047             :     }
    1048             :   else
    1049             :     {
    1050             :       static const unsigned char mse[] =
    1051             :         {
    1052             :           0x80, 1, 0x10, /* Select algorithm RSA. */
    1053             :           0x84, 1, 0x81  /* Select local secret key 1 for decryption. */
    1054             :         };
    1055           0 :       rc = iso7816_manage_security_env (app->slot, 0xC1, 0xB8,
    1056             :                                         mse, sizeof mse);
    1057             : 
    1058             :     }
    1059             : 
    1060           0 :   if (!rc)
    1061           0 :     rc = verify_pin (app, 0, NULL, pincb, pincb_arg);
    1062             : 
    1063             :   /* Note that we need to use extended length APDUs for TCOS 3 cards.
    1064             :      Command chaining does not work.  */
    1065           0 :   if (!rc)
    1066           0 :     rc = iso7816_decipher (app->slot, app->app_local->nks_version > 2? 1:0,
    1067             :                            indata, indatalen, 0, 0x81,
    1068             :                            outdata, outdatalen);
    1069           0 :   return rc;
    1070             : }
    1071             : 
    1072             : 
    1073             : 
    1074             : /* Parse a password ID string.  Returns NULL on error or a string
    1075             :    suitable as passphrase prompt on success.  On success stores the
    1076             :    reference value for the password at R_PWID and a flag indicating
    1077             :    that the SigG application is to be used at R_SIGG.  If NEW_MODE is
    1078             :    true, the returned description is suitable for a new Password.
    1079             :    Supported values for PWIDSTR are:
    1080             : 
    1081             :      PW1.CH       - Global password 1
    1082             :      PW2.CH       - Global password 2
    1083             :      PW1.CH.SIG   - SigG password 1
    1084             :      PW2.CH.SIG   - SigG password 2
    1085             :  */
    1086             : static const char *
    1087           0 : parse_pwidstr (const char *pwidstr, int new_mode, int *r_sigg, int *r_pwid)
    1088             : {
    1089             :   const char *desc;
    1090             : 
    1091           0 :   if (!pwidstr)
    1092           0 :     desc = NULL;
    1093           0 :   else if (!strcmp (pwidstr, "PW1.CH"))
    1094             :     {
    1095           0 :       *r_sigg = 0;
    1096           0 :       *r_pwid = 0x00;
    1097             :       /* TRANSLATORS: Do not translate the "|*|" prefixes but keep
    1098             :          them verbatim at the start of the string.  */
    1099           0 :       desc = (new_mode
    1100             :               ? _("|N|Please enter a new PIN for the standard keys.")
    1101             :               : _("||Please enter the PIN for the standard keys."));
    1102             :     }
    1103           0 :   else if (!strcmp (pwidstr, "PW2.CH"))
    1104             :     {
    1105           0 :       *r_pwid = 0x01;
    1106           0 :       desc = (new_mode
    1107             :               ? _("|NP|Please enter a new PIN Unblocking Code (PUK) "
    1108             :                   "for the standard keys.")
    1109             :               : _("|P|Please enter the PIN Unblocking Code (PUK) "
    1110             :                   "for the standard keys."));
    1111             :     }
    1112           0 :   else if (!strcmp (pwidstr, "PW1.CH.SIG"))
    1113             :     {
    1114           0 :       *r_pwid = 0x81;
    1115           0 :       *r_sigg = 1;
    1116           0 :       desc = (new_mode
    1117             :               ? _("|N|Please enter a new PIN for the key to create "
    1118             :                   "qualified signatures.")
    1119             :               : _("||Please enter the PIN for the key to create "
    1120             :                   "qualified signatures."));
    1121             :     }
    1122           0 :   else if (!strcmp (pwidstr, "PW2.CH.SIG"))
    1123             :     {
    1124           0 :       *r_pwid = 0x83;  /* Yes, that is 83 and not 82.  */
    1125           0 :       *r_sigg = 1;
    1126           0 :       desc = (new_mode
    1127             :               ? _("|NP|Please enter a new PIN Unblocking Code (PUK) "
    1128             :                   "for the key to create qualified signatures.")
    1129             :               : _("|P|Please enter the PIN Unblocking Code (PUK) "
    1130             :                   "for the key to create qualified signatures."));
    1131             :     }
    1132             :   else
    1133             :     {
    1134           0 :       *r_pwid = 0; /* Only to avoid gcc warning in calling function.  */
    1135           0 :       desc = NULL; /* Error.  */
    1136             :     }
    1137             : 
    1138           0 :   return desc;
    1139             : }
    1140             : 
    1141             : 
    1142             : /* Handle the PASSWD command. See parse_pwidstr() for allowed values
    1143             :    for CHVNOSTR.  */
    1144             : static gpg_error_t
    1145           0 : do_change_pin (app_t app, ctrl_t ctrl,  const char *pwidstr,
    1146             :                unsigned int flags,
    1147             :                gpg_error_t (*pincb)(void*, const char *, char **),
    1148             :                void *pincb_arg)
    1149             : {
    1150             :   gpg_error_t err;
    1151           0 :   char *newpin = NULL;
    1152           0 :   char *oldpin = NULL;
    1153             :   size_t newpinlen;
    1154             :   size_t oldpinlen;
    1155             :   int is_sigg;
    1156             :   const char *newdesc;
    1157             :   int pwid;
    1158             :   pininfo_t pininfo;
    1159             : 
    1160             :   (void)ctrl;
    1161             : 
    1162             :   /* The minimum length is enforced by TCOS, the maximum length is
    1163             :      just a reasonable value.  */
    1164           0 :   memset (&pininfo, 0, sizeof pininfo);
    1165           0 :   pininfo.minlen = 6;
    1166           0 :   pininfo.maxlen = 16;
    1167             : 
    1168           0 :   newdesc = parse_pwidstr (pwidstr, 1, &is_sigg, &pwid);
    1169           0 :   if (!newdesc)
    1170           0 :     return gpg_error (GPG_ERR_INV_ID);
    1171             : 
    1172           0 :   err = switch_application (app, is_sigg);
    1173           0 :   if (err)
    1174           0 :     return err;
    1175             : 
    1176           0 :   if ((flags & APP_CHANGE_FLAG_NULLPIN))
    1177             :     {
    1178             :       /* With the nullpin flag, we do not verify the PIN - it would
    1179             :          fail if the Nullpin is still set.  */
    1180           0 :       oldpin = xtrycalloc (1, 6);
    1181           0 :       if (!oldpin)
    1182             :         {
    1183           0 :           err = gpg_error_from_syserror ();
    1184           0 :           goto leave;
    1185             :         }
    1186           0 :       oldpinlen = 6;
    1187             :     }
    1188             :   else
    1189             :     {
    1190             :       const char *desc;
    1191             :       int dummy1, dummy2;
    1192             : 
    1193           0 :       if ((flags & APP_CHANGE_FLAG_RESET))
    1194             :         {
    1195             :           /* Reset mode: Ask for the alternate PIN.  */
    1196             :           const char *altpwidstr;
    1197             : 
    1198           0 :           if (!strcmp (pwidstr, "PW1.CH"))
    1199           0 :             altpwidstr = "PW2.CH";
    1200           0 :           else if (!strcmp (pwidstr, "PW2.CH"))
    1201           0 :             altpwidstr = "PW1.CH";
    1202           0 :           else if (!strcmp (pwidstr, "PW1.CH.SIG"))
    1203           0 :             altpwidstr = "PW2.CH.SIG";
    1204           0 :           else if (!strcmp (pwidstr, "PW2.CH.SIG"))
    1205           0 :             altpwidstr = "PW1.CH.SIG";
    1206             :           else
    1207             :             {
    1208           0 :               err = gpg_error (GPG_ERR_BUG);
    1209           0 :               goto leave;
    1210             :             }
    1211           0 :           desc = parse_pwidstr (altpwidstr, 0, &dummy1, &dummy2);
    1212             :         }
    1213             :       else
    1214             :         {
    1215             :           /* Regular change mode:  Ask for the old PIN.  */
    1216           0 :           desc = parse_pwidstr (pwidstr, 0, &dummy1, &dummy2);
    1217             :         }
    1218           0 :       err = pincb (pincb_arg, desc, &oldpin);
    1219           0 :       if (err)
    1220             :         {
    1221           0 :           log_error ("error getting old PIN: %s\n", gpg_strerror (err));
    1222           0 :           goto leave;
    1223             :         }
    1224           0 :       oldpinlen = strlen (oldpin);
    1225           0 :       err = basic_pin_checks (oldpin, pininfo.minlen, pininfo.maxlen);
    1226           0 :       if (err)
    1227           0 :         goto leave;
    1228             :     }
    1229             : 
    1230           0 :   err = pincb (pincb_arg, newdesc, &newpin);
    1231           0 :   if (err)
    1232             :     {
    1233           0 :       log_error (_("error getting new PIN: %s\n"), gpg_strerror (err));
    1234           0 :       goto leave;
    1235             :     }
    1236           0 :   newpinlen = strlen (newpin);
    1237             : 
    1238           0 :   err = basic_pin_checks (newpin, pininfo.minlen, pininfo.maxlen);
    1239           0 :   if (err)
    1240           0 :     goto leave;
    1241             : 
    1242           0 :   if ((flags & APP_CHANGE_FLAG_RESET))
    1243             :     {
    1244             :       char *data;
    1245           0 :       size_t datalen = oldpinlen + newpinlen;
    1246             : 
    1247           0 :       data = xtrymalloc (datalen);
    1248           0 :       if (!data)
    1249             :         {
    1250           0 :           err = gpg_error_from_syserror ();
    1251           0 :           goto leave;
    1252             :         }
    1253           0 :       memcpy (data, oldpin, oldpinlen);
    1254           0 :       memcpy (data+oldpinlen, newpin, newpinlen);
    1255           0 :       err = iso7816_reset_retry_counter_with_rc (app->slot, pwid,
    1256             :                                                  data, datalen);
    1257           0 :       wipememory (data, datalen);
    1258           0 :       xfree (data);
    1259             :     }
    1260             :   else
    1261           0 :     err = iso7816_change_reference_data (app->slot, pwid,
    1262             :                                          oldpin, oldpinlen,
    1263             :                                          newpin, newpinlen);
    1264             :  leave:
    1265           0 :   xfree (oldpin);
    1266           0 :   xfree (newpin);
    1267           0 :   return err;
    1268             : }
    1269             : 
    1270             : 
    1271             : /* Perform a simple verify operation.  KEYIDSTR should be NULL or empty.  */
    1272             : static gpg_error_t
    1273           0 : do_check_pin (app_t app, const char *pwidstr,
    1274             :               gpg_error_t (*pincb)(void*, const char *, char **),
    1275             :               void *pincb_arg)
    1276             : {
    1277             :   gpg_error_t err;
    1278             :   int pwid;
    1279             :   int is_sigg;
    1280             :   const char *desc;
    1281             : 
    1282           0 :   desc = parse_pwidstr (pwidstr, 0, &is_sigg, &pwid);
    1283           0 :   if (!desc)
    1284           0 :     return gpg_error (GPG_ERR_INV_ID);
    1285             : 
    1286           0 :   err = switch_application (app, is_sigg);
    1287           0 :   if (err)
    1288           0 :     return err;
    1289             : 
    1290           0 :   return verify_pin (app, pwid, desc, pincb, pincb_arg);
    1291             : }
    1292             : 
    1293             : 
    1294             : /* Return the version of the NKS application.  */
    1295             : static int
    1296           0 : get_nks_version (int slot)
    1297             : {
    1298           0 :   unsigned char *result = NULL;
    1299             :   size_t resultlen;
    1300             :   int type;
    1301             : 
    1302           0 :   if (iso7816_apdu_direct (slot, "\x80\xaa\x06\x00\x00", 5, 0,
    1303             :                            &result, &resultlen))
    1304           0 :     return 2; /* NKS 2 does not support this command.  */
    1305             : 
    1306             :   /* Example value:    04 11 19 22 21 6A 20 80 03 03 01 01 01 00 00 00
    1307             :                        vv tt ccccccccccccccccc aa bb cc vvvvvvvvvvv xx
    1308             :      vendor (Philips) -+  |  |                 |  |  |  |           |
    1309             :      chip type -----------+  |                 |  |  |  |           |
    1310             :      chip id ----------------+                 |  |  |  |           |
    1311             :      card type (3 - tcos 3) -------------------+  |  |  |           |
    1312             :      OS version of card type ---------------------+  |  |           |
    1313             :      OS release of card type ------------------------+  |           |
    1314             :      OS vendor internal version ------------------------+           |
    1315             :      RFU -----------------------------------------------------------+
    1316             :   */
    1317           0 :   if (resultlen < 16)
    1318           0 :     type = 0;  /* Invalid data returned.  */
    1319             :   else
    1320           0 :     type = result[8];
    1321           0 :   xfree (result);
    1322             : 
    1323           0 :   return type;
    1324             : }
    1325             : 
    1326             : 
    1327             : /* If ENABLE_SIGG is true switch to the SigG application if not yet
    1328             :    active.  If false switch to the NKS application if not yet active.
    1329             :    Returns 0 on success.  */
    1330             : static gpg_error_t
    1331           0 : switch_application (app_t app, int enable_sigg)
    1332             : {
    1333             :   gpg_error_t err;
    1334             : 
    1335           0 :   if (((app->app_local->sigg_active && enable_sigg)
    1336           0 :        || (!app->app_local->sigg_active && !enable_sigg))
    1337           0 :       && !app->app_local->need_app_select)
    1338           0 :     return 0;  /* Already switched.  */
    1339             : 
    1340           0 :   log_info ("app-nks: switching to %s\n", enable_sigg? "SigG":"NKS");
    1341           0 :   if (enable_sigg)
    1342           0 :     err = iso7816_select_application (app->slot, aid_sigg, sizeof aid_sigg, 0);
    1343             :   else
    1344           0 :     err = iso7816_select_application (app->slot, aid_nks, sizeof aid_nks, 0);
    1345             : 
    1346           0 :   if (!err && enable_sigg && app->app_local->nks_version >= 3
    1347           0 :       && !app->app_local->sigg_msig_checked)
    1348             :     {
    1349             :       /* Check whether this card is a mass signature card.  */
    1350             :       unsigned char *buffer;
    1351             :       size_t buflen;
    1352             :       const unsigned char *tmpl;
    1353             :       size_t tmpllen;
    1354             : 
    1355           0 :       app->app_local->sigg_msig_checked = 1;
    1356           0 :       app->app_local->sigg_is_msig = 1;
    1357           0 :       err = iso7816_select_file (app->slot, 0x5349, 0, NULL, NULL);
    1358           0 :       if (!err)
    1359           0 :         err = iso7816_read_record (app->slot, 1, 1, 0, &buffer, &buflen);
    1360           0 :       if (!err)
    1361             :         {
    1362           0 :           tmpl = find_tlv (buffer, buflen, 0x7a, &tmpllen);
    1363           0 :           if (tmpl && tmpllen == 12
    1364           0 :               && !memcmp (tmpl,
    1365             :                           "\x93\x02\x00\x01\xA4\x06\x83\x01\x81\x83\x01\x83",
    1366             :                           12))
    1367           0 :             app->app_local->sigg_is_msig = 0;
    1368           0 :           xfree (buffer);
    1369             :         }
    1370           0 :       if (app->app_local->sigg_is_msig)
    1371           0 :         log_info ("This is a mass signature card\n");
    1372             :     }
    1373             : 
    1374           0 :   if (!err)
    1375             :     {
    1376           0 :       app->app_local->need_app_select = 0;
    1377           0 :       app->app_local->sigg_active = enable_sigg;
    1378             :     }
    1379             :   else
    1380           0 :     log_error ("app-nks: error switching to %s: %s\n",
    1381             :                enable_sigg? "SigG":"NKS", gpg_strerror (err));
    1382             : 
    1383           0 :   return err;
    1384             : }
    1385             : 
    1386             : 
    1387             : /* Select the NKS application.  */
    1388             : gpg_error_t
    1389           0 : app_select_nks (app_t app)
    1390             : {
    1391           0 :   int slot = app->slot;
    1392             :   int rc;
    1393             : 
    1394           0 :   rc = iso7816_select_application (slot, aid_nks, sizeof aid_nks, 0);
    1395           0 :   if (!rc)
    1396             :     {
    1397           0 :       app->apptype = "NKS";
    1398             : 
    1399           0 :       app->app_local = xtrycalloc (1, sizeof *app->app_local);
    1400           0 :       if (!app->app_local)
    1401             :         {
    1402           0 :           rc = gpg_error (gpg_err_code_from_errno (errno));
    1403           0 :           goto leave;
    1404             :         }
    1405             : 
    1406           0 :       app->app_local->nks_version = get_nks_version (slot);
    1407           0 :       if (opt.verbose)
    1408           0 :         log_info ("Detected NKS version: %d\n", app->app_local->nks_version);
    1409             : 
    1410           0 :       app->fnc.deinit = do_deinit;
    1411           0 :       app->fnc.learn_status = do_learn_status;
    1412           0 :       app->fnc.readcert = do_readcert;
    1413           0 :       app->fnc.readkey = do_readkey;
    1414           0 :       app->fnc.getattr = do_getattr;
    1415           0 :       app->fnc.setattr = NULL;
    1416           0 :       app->fnc.writekey = do_writekey;
    1417           0 :       app->fnc.genkey = NULL;
    1418           0 :       app->fnc.sign = do_sign;
    1419           0 :       app->fnc.auth = NULL;
    1420           0 :       app->fnc.decipher = do_decipher;
    1421           0 :       app->fnc.change_pin = do_change_pin;
    1422           0 :       app->fnc.check_pin = do_check_pin;
    1423             :    }
    1424             : 
    1425             :  leave:
    1426           0 :   if (rc)
    1427           0 :     do_deinit (app);
    1428           0 :   return rc;
    1429             : }

Generated by: LCOV version 1.11