LCOV - code coverage report
Current view: top level - g10 - card-util.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 1039 0.0 %
Date: 2016-09-12 12:29:17 Functions: 0 40 0.0 %

          Line data    Source code
       1             : /* card-util.c - Utility functions for the OpenPGP card.
       2             :  * Copyright (C) 2003-2005, 2009 Free Software Foundation, Inc.
       3             :  * Copyright (C) 2003-2005, 2009 Werner Koch
       4             :  *
       5             :  * This file is part of GnuPG.
       6             :  *
       7             :  * GnuPG is free software; you can redistribute it and/or modify
       8             :  * it under the terms of the GNU General Public License as published by
       9             :  * the Free Software Foundation; either version 3 of the License, or
      10             :  * (at your option) any later version.
      11             :  *
      12             :  * GnuPG is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :  * GNU General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License
      18             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      19             :  */
      20             : 
      21             : #include <config.h>
      22             : #include <stdio.h>
      23             : #include <stdlib.h>
      24             : #include <string.h>
      25             : #include <errno.h>
      26             : #ifdef HAVE_LIBREADLINE
      27             : # define GNUPG_LIBREADLINE_H_INCLUDED
      28             : # include <readline/readline.h>
      29             : #endif /*HAVE_LIBREADLINE*/
      30             : 
      31             : #if GNUPG_MAJOR_VERSION != 1
      32             : # include "gpg.h"
      33             : #endif /*GNUPG_MAJOR_VERSION != 1*/
      34             : #include "util.h"
      35             : #include "i18n.h"
      36             : #include "ttyio.h"
      37             : #include "status.h"
      38             : #include "options.h"
      39             : #include "main.h"
      40             : #include "keyserver-internal.h"
      41             : 
      42             : #if GNUPG_MAJOR_VERSION == 1
      43             : # include "cardglue.h"
      44             : #else /*GNUPG_MAJOR_VERSION!=1*/
      45             : # include "call-agent.h"
      46             : #endif /*GNUPG_MAJOR_VERSION!=1*/
      47             : 
      48             : #define CONTROL_D ('D' - 'A' + 1)
      49             : 
      50             : 
      51             : static void
      52           0 : write_sc_op_status (gpg_error_t err)
      53             : {
      54           0 :   switch (gpg_err_code (err))
      55             :     {
      56             :     case 0:
      57           0 :       write_status (STATUS_SC_OP_SUCCESS);
      58           0 :       break;
      59             : #if GNUPG_MAJOR_VERSION != 1
      60             :     case GPG_ERR_CANCELED:
      61             :     case GPG_ERR_FULLY_CANCELED:
      62           0 :       write_status_text (STATUS_SC_OP_FAILURE, "1");
      63           0 :       break;
      64             :     case GPG_ERR_BAD_PIN:
      65           0 :       write_status_text (STATUS_SC_OP_FAILURE, "2");
      66           0 :       break;
      67             :     default:
      68           0 :       write_status (STATUS_SC_OP_FAILURE);
      69           0 :       break;
      70             : #endif /* GNUPG_MAJOR_VERSION != 1 */
      71             :     }
      72           0 : }
      73             : 
      74             : 
      75             : /* Change the PIN of a an OpenPGP card.  This is an interactive
      76             :    function. */
      77             : void
      78           0 : change_pin (int unblock_v2, int allow_admin)
      79             : {
      80             :   struct agent_card_info_s info;
      81             :   int rc;
      82             : 
      83           0 :   rc = agent_scd_learn (&info, 0);
      84           0 :   if (rc)
      85             :     {
      86           0 :       log_error (_("OpenPGP card not available: %s\n"),
      87             :                   gpg_strerror (rc));
      88           0 :       return;
      89             :     }
      90             : 
      91           0 :   log_info (_("OpenPGP card no. %s detected\n"),
      92           0 :               info.serialno? info.serialno : "[none]");
      93             : 
      94           0 :   agent_clear_pin_cache (info.serialno);
      95             : 
      96           0 :   if (opt.batch)
      97             :     {
      98           0 :       agent_release_card_info (&info);
      99           0 :       log_error (_("can't do this in batch mode\n"));
     100           0 :       return;
     101             :     }
     102             : 
     103             : 
     104           0 :   if (unblock_v2)
     105             :     {
     106           0 :       if (!info.is_v2)
     107           0 :         log_error (_("This command is only available for version 2 cards\n"));
     108           0 :       else if (!info.chvretry[1])
     109           0 :         log_error (_("Reset Code not or not anymore available\n"));
     110             :       else
     111             :         {
     112           0 :           rc = agent_scd_change_pin (2, info.serialno);
     113           0 :           write_sc_op_status (rc);
     114           0 :           if (rc)
     115           0 :             tty_printf ("Error changing the PIN: %s\n", gpg_strerror (rc));
     116             :           else
     117           0 :             tty_printf ("PIN changed.\n");
     118             :         }
     119             :     }
     120           0 :   else if (!allow_admin)
     121             :     {
     122           0 :       rc = agent_scd_change_pin (1, info.serialno);
     123           0 :       write_sc_op_status (rc);
     124           0 :       if (rc)
     125           0 :         tty_printf ("Error changing the PIN: %s\n", gpg_strerror (rc));
     126             :       else
     127           0 :         tty_printf ("PIN changed.\n");
     128             :     }
     129             :   else
     130             :     for (;;)
     131             :       {
     132             :         char *answer;
     133             : 
     134           0 :         tty_printf ("\n");
     135           0 :         tty_printf ("1 - change PIN\n"
     136             :                     "2 - unblock PIN\n"
     137             :                     "3 - change Admin PIN\n"
     138             :                     "4 - set the Reset Code\n"
     139             :                     "Q - quit\n");
     140           0 :         tty_printf ("\n");
     141             : 
     142           0 :         answer = cpr_get("cardutil.change_pin.menu",_("Your selection? "));
     143           0 :         cpr_kill_prompt();
     144           0 :         if (strlen (answer) != 1)
     145           0 :           continue;
     146             : 
     147           0 :         if (*answer == '1')
     148             :           {
     149             :             /* Change PIN.  */
     150           0 :             rc = agent_scd_change_pin (1, info.serialno);
     151           0 :             write_sc_op_status (rc);
     152           0 :             if (rc)
     153           0 :               tty_printf ("Error changing the PIN: %s\n", gpg_strerror (rc));
     154             :             else
     155           0 :               tty_printf ("PIN changed.\n");
     156             :           }
     157           0 :         else if (*answer == '2')
     158             :           {
     159             :             /* Unblock PIN.  */
     160           0 :             rc = agent_scd_change_pin (101, info.serialno);
     161           0 :             write_sc_op_status (rc);
     162           0 :             if (rc)
     163           0 :               tty_printf ("Error unblocking the PIN: %s\n", gpg_strerror (rc));
     164             :             else
     165           0 :               tty_printf ("PIN unblocked and new PIN set.\n");
     166             :           }
     167           0 :         else if (*answer == '3')
     168             :           {
     169             :             /* Change Admin PIN.  */
     170           0 :             rc = agent_scd_change_pin (3, info.serialno);
     171           0 :             write_sc_op_status (rc);
     172           0 :             if (rc)
     173           0 :               tty_printf ("Error changing the PIN: %s\n", gpg_strerror (rc));
     174             :             else
     175           0 :               tty_printf ("PIN changed.\n");
     176             :           }
     177           0 :         else if (*answer == '4')
     178             :           {
     179             :             /* Set a new Reset Code.  */
     180           0 :             rc = agent_scd_change_pin (102, info.serialno);
     181           0 :             write_sc_op_status (rc);
     182           0 :             if (rc)
     183           0 :               tty_printf ("Error setting the Reset Code: %s\n",
     184             :                           gpg_strerror (rc));
     185             :             else
     186           0 :               tty_printf ("Reset Code set.\n");
     187             :           }
     188           0 :         else if (*answer == 'q' || *answer == 'Q')
     189             :           {
     190             :             break;
     191             :           }
     192           0 :       }
     193             : 
     194           0 :   agent_release_card_info (&info);
     195             : }
     196             : 
     197             : static const char *
     198           0 : get_manufacturer (unsigned int no)
     199             : {
     200             :   /* Note:  Make sure that there is no colon or linefeed in the string. */
     201           0 :   switch (no)
     202             :     {
     203           0 :     case 0x0001: return "PPC Card Systems";
     204           0 :     case 0x0002: return "Prism";
     205           0 :     case 0x0003: return "OpenFortress";
     206           0 :     case 0x0004: return "Wewid";
     207           0 :     case 0x0005: return "ZeitControl";
     208           0 :     case 0x0006: return "Yubico";
     209           0 :     case 0x0007: return "OpenKMS";
     210           0 :     case 0x0008: return "LogoEmail";
     211           0 :     case 0x0009: return "Fidesmo";
     212           0 :     case 0x000A: return "Dangerous Things";
     213             : 
     214           0 :     case 0x002A: return "Magrathea";
     215             : 
     216           0 :     case 0x1337: return "Warsaw Hackerspace";
     217           0 :     case 0x2342: return "warpzone"; /* hackerspace Muenster.  */
     218           0 :     case 0xF517: return "FSIJ";
     219             : 
     220             :       /* 0x0000 and 0xFFFF are defined as test cards per spec,
     221             :          0xFF00 to 0xFFFE are assigned for use with randomly created
     222             :          serial numbers.  */
     223             :     case 0x0000:
     224           0 :     case 0xffff: return "test card";
     225           0 :     default: return (no & 0xff00) == 0xff00? "unmanaged S/N range":"unknown";
     226             :     }
     227             : }
     228             : 
     229             : 
     230             : static void
     231           0 : print_sha1_fpr (estream_t fp, const unsigned char *fpr)
     232             : {
     233             :   int i;
     234             : 
     235           0 :   if (fpr)
     236             :     {
     237           0 :       for (i=0; i < 20 ; i+=2, fpr += 2 )
     238             :         {
     239           0 :           if (i == 10 )
     240           0 :             tty_fprintf (fp, " ");
     241           0 :           tty_fprintf (fp, " %02X%02X", *fpr, fpr[1]);
     242             :         }
     243             :     }
     244             :   else
     245           0 :     tty_fprintf (fp, " [none]");
     246           0 :   tty_fprintf (fp, "\n");
     247           0 : }
     248             : 
     249             : 
     250             : static void
     251           0 : print_sha1_fpr_colon (estream_t fp, const unsigned char *fpr)
     252             : {
     253             :   int i;
     254             : 
     255           0 :   if (fpr)
     256             :     {
     257           0 :       for (i=0; i < 20 ; i++, fpr++)
     258           0 :         es_fprintf (fp, "%02X", *fpr);
     259             :     }
     260           0 :   es_putc (':', fp);
     261           0 : }
     262             : 
     263             : 
     264             : static void
     265           0 : print_name (estream_t fp, const char *text, const char *name)
     266             : {
     267           0 :   tty_fprintf (fp, "%s", text);
     268             : 
     269             :   /* FIXME: tty_printf_utf8_string2 eats everything after and
     270             :      including an @ - e.g. when printing an url. */
     271           0 :   if (name && *name)
     272             :     {
     273           0 :       if (fp)
     274           0 :         print_utf8_buffer2 (fp, name, strlen (name), '\n');
     275             :       else
     276           0 :         tty_print_utf8_string2 (NULL, name, strlen (name), 0);
     277             :     }
     278             :   else
     279           0 :     tty_fprintf (fp, _("[not set]"));
     280           0 :   tty_fprintf (fp, "\n");
     281           0 : }
     282             : 
     283             : static void
     284           0 : print_isoname (estream_t fp, const char *text,
     285             :                const char *tag, const char *name)
     286             : {
     287           0 :   if (opt.with_colons)
     288           0 :     es_fprintf (fp, "%s:", tag);
     289             :   else
     290           0 :     tty_fprintf (fp, "%s", text);
     291             : 
     292           0 :   if (name && *name)
     293           0 :     {
     294           0 :       char *p, *given, *buf = xstrdup (name);
     295             : 
     296           0 :       given = strstr (buf, "<<");
     297           0 :       for (p=buf; *p; p++)
     298           0 :         if (*p == '<')
     299           0 :           *p = ' ';
     300           0 :       if (given && given[2])
     301             :         {
     302           0 :           *given = 0;
     303           0 :           given += 2;
     304           0 :           if (opt.with_colons)
     305           0 :             es_write_sanitized (fp, given, strlen (given), ":", NULL);
     306           0 :           else if (fp)
     307           0 :             print_utf8_buffer2 (fp, given, strlen (given), '\n');
     308             :           else
     309           0 :             tty_print_utf8_string2 (NULL, given, strlen (given), 0);
     310             : 
     311           0 :           if (opt.with_colons)
     312           0 :             es_putc (':', fp);
     313           0 :           else if (*buf)
     314           0 :             tty_fprintf (fp, " ");
     315             :         }
     316             : 
     317           0 :       if (opt.with_colons)
     318           0 :         es_write_sanitized (fp, buf, strlen (buf), ":", NULL);
     319           0 :       else if (fp)
     320           0 :         print_utf8_buffer2 (fp, buf, strlen (buf), '\n');
     321             :       else
     322           0 :         tty_print_utf8_string2 (NULL, buf, strlen (buf), 0);
     323           0 :       xfree (buf);
     324             :     }
     325             :   else
     326             :     {
     327           0 :       if (opt.with_colons)
     328           0 :         es_putc (':', fp);
     329             :       else
     330           0 :         tty_fprintf (fp, _("[not set]"));
     331             :     }
     332             : 
     333           0 :   if (opt.with_colons)
     334           0 :     es_fputs (":\n", fp);
     335             :   else
     336           0 :     tty_fprintf (fp, "\n");
     337           0 : }
     338             : 
     339             : /* Return true if the SHA1 fingerprint FPR consists only of zeroes. */
     340             : static int
     341           0 : fpr_is_zero (const char *fpr)
     342             : {
     343             :   int i;
     344             : 
     345           0 :   for (i=0; i < 20 && !fpr[i]; i++)
     346             :     ;
     347           0 :   return (i == 20);
     348             : }
     349             : 
     350             : 
     351             : /* Return true if the SHA1 fingerprint FPR consists only of 0xFF. */
     352             : static int
     353           0 : fpr_is_ff (const char *fpr)
     354             : {
     355             :   int i;
     356             : 
     357           0 :   for (i=0; i < 20 && fpr[i] == '\xff'; i++)
     358             :     ;
     359           0 :   return (i == 20);
     360             : }
     361             : 
     362             : 
     363             : /* Print all available information about the current card. */
     364             : void
     365           0 : card_status (estream_t fp, char *serialno, size_t serialnobuflen)
     366             : {
     367             :   struct agent_card_info_s info;
     368           0 :   PKT_public_key *pk = xcalloc (1, sizeof *pk);
     369           0 :   kbnode_t keyblock = NULL;
     370             :   int rc;
     371             :   unsigned int uval;
     372             :   const unsigned char *thefpr;
     373             :   int i;
     374             : 
     375           0 :   if (serialno && serialnobuflen)
     376           0 :     *serialno = 0;
     377             : 
     378           0 :   rc = agent_scd_learn (&info, 0);
     379           0 :   if (rc)
     380             :     {
     381           0 :       if (opt.with_colons)
     382           0 :         es_fputs ("AID:::\n", fp);
     383           0 :       log_error (_("OpenPGP card not available: %s\n"), gpg_strerror (rc));
     384           0 :       xfree (pk);
     385           0 :       return;
     386             :     }
     387             : 
     388           0 :   if (opt.with_colons)
     389           0 :     es_fprintf (fp, "Reader:%s:", info.reader? info.reader : "");
     390             :   else
     391           0 :     tty_fprintf (fp, "Reader ...........: %s\n",
     392           0 :                  info.reader? info.reader : "[none]");
     393           0 :   if (opt.with_colons)
     394           0 :     es_fprintf (fp, "AID:%s:", info.serialno? info.serialno : "");
     395             :   else
     396           0 :     tty_fprintf (fp, "Application ID ...: %s\n",
     397           0 :                  info.serialno? info.serialno : "[none]");
     398           0 :   if (!info.serialno || strncmp (info.serialno, "D27600012401", 12)
     399           0 :       || strlen (info.serialno) != 32 )
     400             :     {
     401           0 :       if (info.apptype && !strcmp (info.apptype, "NKS"))
     402             :         {
     403           0 :           if (opt.with_colons)
     404           0 :             es_fputs ("netkey-card:\n", fp);
     405           0 :           log_info ("this is a NetKey card\n");
     406             :         }
     407           0 :       else if (info.apptype && !strcmp (info.apptype, "DINSIG"))
     408             :         {
     409           0 :           if (opt.with_colons)
     410           0 :             es_fputs ("dinsig-card:\n", fp);
     411           0 :           log_info ("this is a DINSIG compliant card\n");
     412             :         }
     413           0 :       else if (info.apptype && !strcmp (info.apptype, "P15"))
     414             :         {
     415           0 :           if (opt.with_colons)
     416           0 :             es_fputs ("pkcs15-card:\n", fp);
     417           0 :           log_info ("this is a PKCS#15 compliant card\n");
     418             :         }
     419           0 :       else if (info.apptype && !strcmp (info.apptype, "GELDKARTE"))
     420             :         {
     421           0 :           if (opt.with_colons)
     422           0 :             es_fputs ("geldkarte-card:\n", fp);
     423           0 :           log_info ("this is a Geldkarte compliant card\n");
     424             :         }
     425             :       else
     426             :         {
     427           0 :           if (opt.with_colons)
     428           0 :             es_fputs ("unknown:\n", fp);
     429             :         }
     430           0 :       log_info ("not an OpenPGP card\n");
     431           0 :       agent_release_card_info (&info);
     432           0 :       xfree (pk);
     433           0 :       return;
     434             :     }
     435             : 
     436           0 :   if (!serialno)
     437             :     ;
     438           0 :   else if (strlen (serialno)+1 > serialnobuflen)
     439           0 :     log_error ("serial number longer than expected\n");
     440             :   else
     441           0 :     strcpy (serialno, info.serialno);
     442             : 
     443           0 :   if (opt.with_colons)
     444           0 :     es_fputs ("openpgp-card:\n", fp);
     445             : 
     446             : 
     447           0 :   if (opt.with_colons)
     448             :     {
     449           0 :       es_fprintf (fp, "version:%.4s:\n", info.serialno+12);
     450           0 :       uval = xtoi_2(info.serialno+16)*256 + xtoi_2 (info.serialno+18);
     451           0 :       es_fprintf (fp, "vendor:%04x:%s:\n", uval, get_manufacturer (uval));
     452           0 :       es_fprintf (fp, "serial:%.8s:\n", info.serialno+20);
     453             : 
     454           0 :       print_isoname (fp, "Name of cardholder: ", "name", info.disp_name);
     455             : 
     456           0 :       es_fputs ("lang:", fp);
     457           0 :       if (info.disp_lang)
     458           0 :         es_write_sanitized (fp, info.disp_lang, strlen (info.disp_lang),
     459             :                             ":", NULL);
     460           0 :       es_fputs (":\n", fp);
     461             : 
     462           0 :       es_fprintf (fp, "sex:%c:\n", (info.disp_sex == 1? 'm':
     463           0 :                                  info.disp_sex == 2? 'f' : 'u'));
     464             : 
     465           0 :       es_fputs ("url:", fp);
     466           0 :       if (info.pubkey_url)
     467           0 :         es_write_sanitized (fp, info.pubkey_url, strlen (info.pubkey_url),
     468             :                             ":", NULL);
     469           0 :       es_fputs (":\n", fp);
     470             : 
     471           0 :       es_fputs ("login:", fp);
     472           0 :       if (info.login_data)
     473           0 :         es_write_sanitized (fp, info.login_data, strlen (info.login_data),
     474             :                             ":", NULL);
     475           0 :       es_fputs (":\n", fp);
     476             : 
     477           0 :       es_fprintf (fp, "forcepin:%d:::\n", !info.chv1_cached);
     478           0 :       for (i=0; i < DIM (info.key_attr); i++)
     479           0 :         if (info.key_attr[0].algo == PUBKEY_ALGO_RSA)
     480           0 :           es_fprintf (fp, "keyattr:%d:%d:%u:\n", i+1,
     481             :                       info.key_attr[i].algo, info.key_attr[i].nbits);
     482           0 :         else if (info.key_attr[i].algo == PUBKEY_ALGO_ECDH
     483           0 :                  || info.key_attr[i].algo == PUBKEY_ALGO_ECDSA
     484           0 :                  || info.key_attr[i].algo == PUBKEY_ALGO_EDDSA)
     485           0 :           es_fprintf (fp, "keyattr:%d:%d:%s:\n", i+1,
     486             :                       info.key_attr[i].algo, info.key_attr[i].curve);
     487           0 :       es_fprintf (fp, "maxpinlen:%d:%d:%d:\n",
     488             :                   info.chvmaxlen[0], info.chvmaxlen[1], info.chvmaxlen[2]);
     489           0 :       es_fprintf (fp, "pinretry:%d:%d:%d:\n",
     490             :                   info.chvretry[0], info.chvretry[1], info.chvretry[2]);
     491           0 :       es_fprintf (fp, "sigcount:%lu:::\n", info.sig_counter);
     492             : 
     493           0 :       for (i=0; i < 4; i++)
     494             :         {
     495           0 :           if (info.private_do[i])
     496             :             {
     497           0 :               es_fprintf (fp, "private_do:%d:", i+1);
     498           0 :               es_write_sanitized (fp, info.private_do[i],
     499           0 :                                   strlen (info.private_do[i]), ":", NULL);
     500           0 :               es_fputs (":\n", fp);
     501             :             }
     502             :         }
     503             : 
     504           0 :       es_fputs ("cafpr:", fp);
     505           0 :       print_sha1_fpr_colon (fp, info.cafpr1valid? info.cafpr1:NULL);
     506           0 :       print_sha1_fpr_colon (fp, info.cafpr2valid? info.cafpr2:NULL);
     507           0 :       print_sha1_fpr_colon (fp, info.cafpr3valid? info.cafpr3:NULL);
     508           0 :       es_putc ('\n', fp);
     509           0 :       es_fputs ("fpr:", fp);
     510           0 :       print_sha1_fpr_colon (fp, info.fpr1valid? info.fpr1:NULL);
     511           0 :       print_sha1_fpr_colon (fp, info.fpr2valid? info.fpr2:NULL);
     512           0 :       print_sha1_fpr_colon (fp, info.fpr3valid? info.fpr3:NULL);
     513           0 :       es_putc ('\n', fp);
     514           0 :       es_fprintf (fp, "fprtime:%lu:%lu:%lu:\n",
     515           0 :                (unsigned long)info.fpr1time, (unsigned long)info.fpr2time,
     516           0 :                (unsigned long)info.fpr3time);
     517             :     }
     518             :   else
     519             :     {
     520           0 :       tty_fprintf (fp, "Version ..........: %.1s%c.%.1s%c\n",
     521           0 :                    info.serialno[12] == '0'?"":info.serialno+12,
     522           0 :                    info.serialno[13],
     523           0 :                    info.serialno[14] == '0'?"":info.serialno+14,
     524           0 :                    info.serialno[15]);
     525           0 :       tty_fprintf (fp, "Manufacturer .....: %s\n",
     526           0 :                    get_manufacturer (xtoi_2(info.serialno+16)*256
     527           0 :                                      + xtoi_2 (info.serialno+18)));
     528           0 :       tty_fprintf (fp, "Serial number ....: %.8s\n", info.serialno+20);
     529             : 
     530           0 :       print_isoname (fp, "Name of cardholder: ", "name", info.disp_name);
     531           0 :       print_name (fp, "Language prefs ...: ", info.disp_lang);
     532           0 :       tty_fprintf (fp,    "Sex ..............: %s\n",
     533           0 :                    info.disp_sex == 1? _("male"):
     534           0 :                    info.disp_sex == 2? _("female") : _("unspecified"));
     535           0 :       print_name (fp, "URL of public key : ", info.pubkey_url);
     536           0 :       print_name (fp, "Login data .......: ", info.login_data);
     537           0 :       if (info.private_do[0])
     538           0 :         print_name (fp, "Private DO 1 .....: ", info.private_do[0]);
     539           0 :       if (info.private_do[1])
     540           0 :         print_name (fp, "Private DO 2 .....: ", info.private_do[1]);
     541           0 :       if (info.private_do[2])
     542           0 :         print_name (fp, "Private DO 3 .....: ", info.private_do[2]);
     543           0 :       if (info.private_do[3])
     544           0 :         print_name (fp, "Private DO 4 .....: ", info.private_do[3]);
     545           0 :       if (info.cafpr1valid)
     546             :         {
     547           0 :           tty_fprintf (fp, "CA fingerprint %d .:", 1);
     548           0 :           print_sha1_fpr (fp, info.cafpr1);
     549             :         }
     550           0 :       if (info.cafpr2valid)
     551             :         {
     552           0 :           tty_fprintf (fp, "CA fingerprint %d .:", 2);
     553           0 :           print_sha1_fpr (fp, info.cafpr2);
     554             :         }
     555           0 :       if (info.cafpr3valid)
     556             :         {
     557           0 :           tty_fprintf (fp, "CA fingerprint %d .:", 3);
     558           0 :           print_sha1_fpr (fp, info.cafpr3);
     559             :         }
     560           0 :       tty_fprintf (fp,    "Signature PIN ....: %s\n",
     561           0 :                    info.chv1_cached? _("not forced"): _("forced"));
     562           0 :       if (info.key_attr[0].algo)
     563             :         {
     564           0 :           tty_fprintf (fp,    "Key attributes ...:");
     565           0 :           for (i=0; i < DIM (info.key_attr); i++)
     566           0 :             if (info.key_attr[i].algo == PUBKEY_ALGO_RSA)
     567           0 :               tty_fprintf (fp, " rsa%u", info.key_attr[i].nbits);
     568           0 :             else if (info.key_attr[i].algo == PUBKEY_ALGO_ECDH
     569           0 :                      || info.key_attr[i].algo == PUBKEY_ALGO_ECDSA
     570           0 :                      || info.key_attr[i].algo == PUBKEY_ALGO_EDDSA)
     571           0 :               tty_fprintf (fp, " %s", info.key_attr[i].curve);
     572           0 :           tty_fprintf (fp, "\n");
     573             :         }
     574           0 :       tty_fprintf (fp,    "Max. PIN lengths .: %d %d %d\n",
     575             :                    info.chvmaxlen[0], info.chvmaxlen[1], info.chvmaxlen[2]);
     576           0 :       tty_fprintf (fp,    "PIN retry counter : %d %d %d\n",
     577             :                    info.chvretry[0], info.chvretry[1], info.chvretry[2]);
     578           0 :       tty_fprintf (fp,    "Signature counter : %lu\n", info.sig_counter);
     579           0 :       tty_fprintf (fp, "Signature key ....:");
     580           0 :       print_sha1_fpr (fp, info.fpr1valid? info.fpr1:NULL);
     581           0 :       if (info.fpr1valid && info.fpr1time)
     582           0 :         tty_fprintf (fp, "      created ....: %s\n",
     583             :                      isotimestamp (info.fpr1time));
     584           0 :       tty_fprintf (fp, "Encryption key....:");
     585           0 :       print_sha1_fpr (fp, info.fpr2valid? info.fpr2:NULL);
     586           0 :       if (info.fpr2valid && info.fpr2time)
     587           0 :         tty_fprintf (fp, "      created ....: %s\n",
     588             :                      isotimestamp (info.fpr2time));
     589           0 :       tty_fprintf (fp, "Authentication key:");
     590           0 :       print_sha1_fpr (fp, info.fpr3valid? info.fpr3:NULL);
     591           0 :       if (info.fpr3valid && info.fpr3time)
     592           0 :         tty_fprintf (fp, "      created ....: %s\n",
     593             :                      isotimestamp (info.fpr3time));
     594           0 :       tty_fprintf (fp, "General key info..: ");
     595             : 
     596           0 :       thefpr = (info.fpr1valid? info.fpr1 : info.fpr2valid? info.fpr2 :
     597           0 :                 info.fpr3valid? info.fpr3 : NULL);
     598             :       /* If the fingerprint is all 0xff, the key has no asssociated
     599             :          OpenPGP certificate.  */
     600           0 :       if ( thefpr && !fpr_is_ff (thefpr)
     601           0 :            && !get_pubkey_byfprint (pk, &keyblock, thefpr, 20))
     602             :         {
     603           0 :           print_pubkey_info (fp, pk);
     604           0 :           if (keyblock)
     605           0 :             print_card_key_info (fp, keyblock);
     606             :         }
     607             :       else
     608           0 :         tty_fprintf (fp, "[none]\n");
     609             :     }
     610             : 
     611           0 :   release_kbnode (keyblock);
     612           0 :   free_public_key (pk);
     613           0 :   agent_release_card_info (&info);
     614             : }
     615             : 
     616             : 
     617             : static char *
     618           0 : get_one_name (const char *prompt1, const char *prompt2)
     619             : {
     620             :   char *name;
     621             :   int i;
     622             : 
     623             :   for (;;)
     624             :     {
     625           0 :       name = cpr_get (prompt1, prompt2);
     626           0 :       if (!name)
     627           0 :         return NULL;
     628           0 :       trim_spaces (name);
     629           0 :       cpr_kill_prompt ();
     630           0 :       for (i=0; name[i] && name[i] >= ' ' && name[i] <= 126; i++)
     631             :         ;
     632             : 
     633             :       /* The name must be in Latin-1 and not UTF-8 - lacking the code
     634             :          to ensure this we restrict it to ASCII. */
     635           0 :       if (name[i])
     636           0 :         tty_printf (_("Error: Only plain ASCII is currently allowed.\n"));
     637           0 :       else if (strchr (name, '<'))
     638           0 :         tty_printf (_("Error: The \"<\" character may not be used.\n"));
     639           0 :       else if (strstr (name, "  "))
     640           0 :         tty_printf (_("Error: Double spaces are not allowed.\n"));
     641             :       else
     642           0 :         return name;
     643           0 :       xfree (name);
     644           0 :     }
     645             : }
     646             : 
     647             : 
     648             : 
     649             : static int
     650           0 : change_name (void)
     651             : {
     652           0 :   char *surname = NULL, *givenname = NULL;
     653             :   char *isoname, *p;
     654             :   int rc;
     655             : 
     656           0 :   surname = get_one_name ("keygen.smartcard.surname",
     657           0 :                                     _("Cardholder's surname: "));
     658           0 :   givenname = get_one_name ("keygen.smartcard.givenname",
     659           0 :                                        _("Cardholder's given name: "));
     660           0 :   if (!surname || !givenname || (!*surname && !*givenname))
     661             :     {
     662           0 :       xfree (surname);
     663           0 :       xfree (givenname);
     664           0 :       return -1; /*canceled*/
     665             :     }
     666             : 
     667           0 :   isoname = xmalloc ( strlen (surname) + 2 + strlen (givenname) + 1);
     668           0 :   strcpy (stpcpy (stpcpy (isoname, surname), "<<"), givenname);
     669           0 :   xfree (surname);
     670           0 :   xfree (givenname);
     671           0 :   for (p=isoname; *p; p++)
     672           0 :     if (*p == ' ')
     673           0 :       *p = '<';
     674             : 
     675           0 :   if (strlen (isoname) > 39 )
     676             :     {
     677           0 :       tty_printf (_("Error: Combined name too long "
     678             :                     "(limit is %d characters).\n"), 39);
     679           0 :       xfree (isoname);
     680           0 :       return -1;
     681             :     }
     682             : 
     683           0 :   rc = agent_scd_setattr ("DISP-NAME", isoname, strlen (isoname), NULL );
     684           0 :   if (rc)
     685           0 :     log_error ("error setting Name: %s\n", gpg_strerror (rc));
     686             : 
     687           0 :   xfree (isoname);
     688           0 :   return rc;
     689             : }
     690             : 
     691             : 
     692             : static int
     693           0 : change_url (void)
     694             : {
     695             :   char *url;
     696             :   int rc;
     697             : 
     698           0 :   url = cpr_get ("cardedit.change_url", _("URL to retrieve public key: "));
     699           0 :   if (!url)
     700           0 :     return -1;
     701           0 :   trim_spaces (url);
     702           0 :   cpr_kill_prompt ();
     703             : 
     704           0 :   if (strlen (url) > 254 )
     705             :     {
     706           0 :       tty_printf (_("Error: URL too long "
     707             :                     "(limit is %d characters).\n"), 254);
     708           0 :       xfree (url);
     709           0 :       return -1;
     710             :     }
     711             : 
     712           0 :   rc = agent_scd_setattr ("PUBKEY-URL", url, strlen (url), NULL );
     713           0 :   if (rc)
     714           0 :     log_error ("error setting URL: %s\n", gpg_strerror (rc));
     715           0 :   xfree (url);
     716           0 :   write_sc_op_status (rc);
     717           0 :   return rc;
     718             : }
     719             : 
     720             : 
     721             : /* Fetch the key from the URL given on the card or try to get it from
     722             :    the default keyserver.  */
     723             : static int
     724           0 : fetch_url (ctrl_t ctrl)
     725             : {
     726             :   int rc;
     727             :   struct agent_card_info_s info;
     728             : 
     729           0 :   memset(&info,0,sizeof(info));
     730             : 
     731           0 :   rc=agent_scd_getattr("PUBKEY-URL",&info);
     732           0 :   if(rc)
     733           0 :     log_error("error retrieving URL from card: %s\n",gpg_strerror(rc));
     734             :   else
     735             :     {
     736           0 :       rc=agent_scd_getattr("KEY-FPR",&info);
     737           0 :       if(rc)
     738           0 :         log_error("error retrieving key fingerprint from card: %s\n",
     739             :                   gpg_strerror(rc));
     740           0 :       else if (info.pubkey_url && *info.pubkey_url)
     741           0 :         {
     742           0 :           strlist_t sl = NULL;
     743             : 
     744           0 :           add_to_strlist (&sl, info.pubkey_url);
     745           0 :           rc = keyserver_fetch (ctrl, sl);
     746           0 :           free_strlist (sl);
     747             :         }
     748           0 :       else if (info.fpr1valid)
     749             :         {
     750           0 :           rc = keyserver_import_fprint (ctrl, info.fpr1, 20, opt.keyserver);
     751             :         }
     752             :     }
     753             : 
     754           0 :   return rc;
     755             : }
     756             : 
     757             : 
     758             : /* Read data from file FNAME up to MAXLEN characters.  On error return
     759             :    -1 and store NULL at R_BUFFER; on success return the number of
     760             :    bytes read and store the address of a newly allocated buffer at
     761             :    R_BUFFER. */
     762             : static int
     763           0 : get_data_from_file (const char *fname, size_t maxlen, char **r_buffer)
     764             : {
     765             :   estream_t fp;
     766             :   char *data;
     767             :   int n;
     768             : 
     769           0 :   *r_buffer = NULL;
     770             : 
     771           0 :   fp = es_fopen (fname, "rb");
     772             : #if GNUPG_MAJOR_VERSION == 1
     773             :   if (fp && is_secured_file (fileno (fp)))
     774             :     {
     775             :       fclose (fp);
     776             :       fp = NULL;
     777             :       errno = EPERM;
     778             :     }
     779             : #endif
     780           0 :   if (!fp)
     781             :     {
     782           0 :       tty_printf (_("can't open '%s': %s\n"), fname, strerror (errno));
     783           0 :       return -1;
     784             :     }
     785             : 
     786           0 :   data = xtrymalloc (maxlen? maxlen:1);
     787           0 :   if (!data)
     788             :     {
     789           0 :       tty_printf (_("error allocating enough memory: %s\n"), strerror (errno));
     790           0 :       es_fclose (fp);
     791           0 :       return -1;
     792             :     }
     793             : 
     794           0 :   if (maxlen)
     795           0 :     n = es_fread (data, 1, maxlen, fp);
     796             :   else
     797           0 :     n = 0;
     798           0 :   es_fclose (fp);
     799           0 :   if (n < 0)
     800             :     {
     801           0 :       tty_printf (_("error reading '%s': %s\n"), fname, strerror (errno));
     802           0 :       xfree (data);
     803           0 :       return -1;
     804             :     }
     805           0 :   *r_buffer = data;
     806           0 :   return n;
     807             : }
     808             : 
     809             : 
     810             : /* Write LENGTH bytes from BUFFER to file FNAME.  Return 0 on
     811             :    success.  */
     812             : static int
     813           0 : put_data_to_file (const char *fname, const void *buffer, size_t length)
     814             : {
     815             :   estream_t fp;
     816             : 
     817           0 :   fp = es_fopen (fname, "wb");
     818             : #if GNUPG_MAJOR_VERSION == 1
     819             :   if (fp && is_secured_file (fileno (fp)))
     820             :     {
     821             :       fclose (fp);
     822             :       fp = NULL;
     823             :       errno = EPERM;
     824             :     }
     825             : #endif
     826           0 :   if (!fp)
     827             :     {
     828           0 :       tty_printf (_("can't create '%s': %s\n"), fname, strerror (errno));
     829           0 :       return -1;
     830             :     }
     831             : 
     832           0 :   if (length && es_fwrite (buffer, length, 1, fp) != 1)
     833             :     {
     834           0 :       tty_printf (_("error writing '%s': %s\n"), fname, strerror (errno));
     835           0 :       es_fclose (fp);
     836           0 :       return -1;
     837             :     }
     838           0 :   es_fclose (fp);
     839           0 :   return 0;
     840             : }
     841             : 
     842             : 
     843             : static int
     844           0 : change_login (const char *args)
     845             : {
     846             :   char *data;
     847             :   int n;
     848             :   int rc;
     849             : 
     850           0 :   if (args && *args == '<')  /* Read it from a file */
     851             :     {
     852           0 :       for (args++; spacep (args); args++)
     853             :         ;
     854           0 :       n = get_data_from_file (args, 254, &data);
     855           0 :       if (n < 0)
     856           0 :         return -1;
     857             :     }
     858             :   else
     859             :     {
     860           0 :       data = cpr_get ("cardedit.change_login",
     861           0 :                       _("Login data (account name): "));
     862           0 :       if (!data)
     863           0 :         return -1;
     864           0 :       trim_spaces (data);
     865           0 :       cpr_kill_prompt ();
     866           0 :       n = strlen (data);
     867             :     }
     868             : 
     869           0 :   if (n > 254 )
     870             :     {
     871           0 :       tty_printf (_("Error: Login data too long "
     872             :                     "(limit is %d characters).\n"), 254);
     873           0 :       xfree (data);
     874           0 :       return -1;
     875             :     }
     876             : 
     877           0 :   rc = agent_scd_setattr ("LOGIN-DATA", data, n, NULL );
     878           0 :   if (rc)
     879           0 :     log_error ("error setting login data: %s\n", gpg_strerror (rc));
     880           0 :   xfree (data);
     881           0 :   write_sc_op_status (rc);
     882           0 :   return rc;
     883             : }
     884             : 
     885             : static int
     886           0 : change_private_do (const char *args, int nr)
     887             : {
     888           0 :   char do_name[] = "PRIVATE-DO-X";
     889             :   char *data;
     890             :   int n;
     891             :   int rc;
     892             : 
     893           0 :   log_assert (nr >= 1 && nr <= 4);
     894           0 :   do_name[11] = '0' + nr;
     895             : 
     896           0 :   if (args && (args = strchr (args, '<')))  /* Read it from a file */
     897             :     {
     898           0 :       for (args++; spacep (args); args++)
     899             :         ;
     900           0 :       n = get_data_from_file (args, 254, &data);
     901           0 :       if (n < 0)
     902           0 :         return -1;
     903             :     }
     904             :   else
     905             :     {
     906           0 :       data = cpr_get ("cardedit.change_private_do",
     907           0 :                       _("Private DO data: "));
     908           0 :       if (!data)
     909           0 :         return -1;
     910           0 :       trim_spaces (data);
     911           0 :       cpr_kill_prompt ();
     912           0 :       n = strlen (data);
     913             :     }
     914             : 
     915           0 :   if (n > 254 )
     916             :     {
     917           0 :       tty_printf (_("Error: Private DO too long "
     918             :                     "(limit is %d characters).\n"), 254);
     919           0 :       xfree (data);
     920           0 :       return -1;
     921             :     }
     922             : 
     923           0 :   rc = agent_scd_setattr (do_name, data, n, NULL );
     924           0 :   if (rc)
     925           0 :     log_error ("error setting private DO: %s\n", gpg_strerror (rc));
     926           0 :   xfree (data);
     927           0 :   write_sc_op_status (rc);
     928           0 :   return rc;
     929             : }
     930             : 
     931             : 
     932             : static int
     933           0 : change_cert (const char *args)
     934             : {
     935             :   char *data;
     936             :   int n;
     937             :   int rc;
     938             : 
     939           0 :   if (args && *args == '<')  /* Read it from a file */
     940             :     {
     941           0 :       for (args++; spacep (args); args++)
     942             :         ;
     943           0 :       n = get_data_from_file (args, 16384, &data);
     944           0 :       if (n < 0)
     945           0 :         return -1;
     946             :     }
     947             :   else
     948             :     {
     949           0 :       tty_printf ("usage error: redirection to file required\n");
     950           0 :       return -1;
     951             :     }
     952             : 
     953           0 :   rc = agent_scd_writecert ("OPENPGP.3", data, n);
     954           0 :   if (rc)
     955           0 :     log_error ("error writing certificate to card: %s\n", gpg_strerror (rc));
     956           0 :   xfree (data);
     957           0 :   write_sc_op_status (rc);
     958           0 :   return rc;
     959             : }
     960             : 
     961             : 
     962             : static int
     963           0 : read_cert (const char *args)
     964             : {
     965             :   const char *fname;
     966             :   void *buffer;
     967             :   size_t length;
     968             :   int rc;
     969             : 
     970           0 :   if (args && *args == '>')  /* Write it to a file */
     971             :     {
     972           0 :       for (args++; spacep (args); args++)
     973             :         ;
     974           0 :       fname = args;
     975             :     }
     976             :   else
     977             :     {
     978           0 :       tty_printf ("usage error: redirection to file required\n");
     979           0 :       return -1;
     980             :     }
     981             : 
     982           0 :   rc = agent_scd_readcert ("OPENPGP.3", &buffer, &length);
     983           0 :   if (rc)
     984           0 :     log_error ("error reading certificate from card: %s\n", gpg_strerror (rc));
     985             :   else
     986           0 :     rc = put_data_to_file (fname, buffer, length);
     987           0 :   xfree (buffer);
     988           0 :   write_sc_op_status (rc);
     989           0 :   return rc;
     990             : }
     991             : 
     992             : 
     993             : static int
     994           0 : change_lang (void)
     995             : {
     996             :   char *data, *p;
     997             :   int rc;
     998             : 
     999           0 :   data = cpr_get ("cardedit.change_lang",
    1000           0 :                   _("Language preferences: "));
    1001           0 :   if (!data)
    1002           0 :     return -1;
    1003           0 :   trim_spaces (data);
    1004           0 :   cpr_kill_prompt ();
    1005             : 
    1006           0 :   if (strlen (data) > 8 || (strlen (data) & 1))
    1007             :     {
    1008           0 :       tty_printf (_("Error: invalid length of preference string.\n"));
    1009           0 :       xfree (data);
    1010           0 :       return -1;
    1011             :     }
    1012             : 
    1013           0 :   for (p=data; *p && *p >= 'a' && *p <= 'z'; p++)
    1014             :     ;
    1015           0 :   if (*p)
    1016             :     {
    1017           0 :       tty_printf (_("Error: invalid characters in preference string.\n"));
    1018           0 :       xfree (data);
    1019           0 :       return -1;
    1020             :     }
    1021             : 
    1022           0 :   rc = agent_scd_setattr ("DISP-LANG", data, strlen (data), NULL );
    1023           0 :   if (rc)
    1024           0 :     log_error ("error setting lang: %s\n", gpg_strerror (rc));
    1025           0 :   xfree (data);
    1026           0 :   write_sc_op_status (rc);
    1027           0 :   return rc;
    1028             : }
    1029             : 
    1030             : 
    1031             : static int
    1032           0 : change_sex (void)
    1033             : {
    1034             :   char *data;
    1035             :   const char *str;
    1036             :   int rc;
    1037             : 
    1038           0 :   data = cpr_get ("cardedit.change_sex",
    1039           0 :                   _("Sex ((M)ale, (F)emale or space): "));
    1040           0 :   if (!data)
    1041           0 :     return -1;
    1042           0 :   trim_spaces (data);
    1043           0 :   cpr_kill_prompt ();
    1044             : 
    1045           0 :   if (!*data)
    1046           0 :     str = "9";
    1047           0 :   else if ((*data == 'M' || *data == 'm') && !data[1])
    1048           0 :     str = "1";
    1049           0 :   else if ((*data == 'F' || *data == 'f') && !data[1])
    1050           0 :     str = "2";
    1051             :   else
    1052             :     {
    1053           0 :       tty_printf (_("Error: invalid response.\n"));
    1054           0 :       xfree (data);
    1055           0 :       return -1;
    1056             :     }
    1057             : 
    1058           0 :   rc = agent_scd_setattr ("DISP-SEX", str, 1, NULL );
    1059           0 :   if (rc)
    1060           0 :     log_error ("error setting sex: %s\n", gpg_strerror (rc));
    1061           0 :   xfree (data);
    1062           0 :   write_sc_op_status (rc);
    1063           0 :   return rc;
    1064             : }
    1065             : 
    1066             : 
    1067             : static int
    1068           0 : change_cafpr (int fprno)
    1069             : {
    1070             :   char *data;
    1071             :   const char *s;
    1072             :   int i, c, rc;
    1073             :   unsigned char fpr[20];
    1074             : 
    1075           0 :   data = cpr_get ("cardedit.change_cafpr", _("CA fingerprint: "));
    1076           0 :   if (!data)
    1077           0 :     return -1;
    1078           0 :   trim_spaces (data);
    1079           0 :   cpr_kill_prompt ();
    1080             : 
    1081           0 :   for (i=0, s=data; i < 20 && *s; )
    1082             :     {
    1083           0 :       while (spacep(s))
    1084           0 :         s++;
    1085           0 :       if (*s == ':')
    1086           0 :         s++;
    1087           0 :       while (spacep(s))
    1088           0 :         s++;
    1089           0 :       c = hextobyte (s);
    1090           0 :       if (c == -1)
    1091           0 :         break;
    1092           0 :       fpr[i++] = c;
    1093           0 :       s += 2;
    1094             :     }
    1095           0 :   xfree (data);
    1096           0 :   if (i != 20 || *s)
    1097             :     {
    1098           0 :       tty_printf (_("Error: invalid formatted fingerprint.\n"));
    1099           0 :       return -1;
    1100             :     }
    1101             : 
    1102           0 :   rc = agent_scd_setattr (fprno==1?"CA-FPR-1":
    1103             :                           fprno==2?"CA-FPR-2":
    1104             :                           fprno==3?"CA-FPR-3":"x", fpr, 20, NULL );
    1105           0 :   if (rc)
    1106           0 :     log_error ("error setting cafpr: %s\n", gpg_strerror (rc));
    1107           0 :   write_sc_op_status (rc);
    1108           0 :   return rc;
    1109             : }
    1110             : 
    1111             : 
    1112             : 
    1113             : static void
    1114           0 : toggle_forcesig (void)
    1115             : {
    1116             :   struct agent_card_info_s info;
    1117             :   int rc;
    1118             :   int newstate;
    1119             : 
    1120           0 :   memset (&info, 0, sizeof info);
    1121           0 :   rc = agent_scd_getattr ("CHV-STATUS", &info);
    1122           0 :   if (rc)
    1123             :     {
    1124           0 :       log_error ("error getting current status: %s\n", gpg_strerror (rc));
    1125           0 :       return;
    1126             :     }
    1127           0 :   newstate = !info.chv1_cached;
    1128           0 :   agent_release_card_info (&info);
    1129             : 
    1130           0 :   rc = agent_scd_setattr ("CHV-STATUS-1", newstate? "\x01":"", 1, NULL);
    1131           0 :   if (rc)
    1132           0 :     log_error ("error toggling signature PIN flag: %s\n", gpg_strerror (rc));
    1133           0 :   write_sc_op_status (rc);
    1134             : }
    1135             : 
    1136             : 
    1137             : /* Helper for the key generation/edit functions.  */
    1138             : static int
    1139           0 : get_info_for_key_operation (struct agent_card_info_s *info)
    1140             : {
    1141             :   int rc;
    1142             : 
    1143           0 :   memset (info, 0, sizeof *info);
    1144           0 :   rc = agent_scd_getattr ("SERIALNO", info);
    1145           0 :   if (rc || !info->serialno || strncmp (info->serialno, "D27600012401", 12)
    1146           0 :       || strlen (info->serialno) != 32 )
    1147             :     {
    1148           0 :       log_error (_("key operation not possible: %s\n"),
    1149           0 :                  rc ? gpg_strerror (rc) : _("not an OpenPGP card"));
    1150           0 :       return rc? rc: -1;
    1151             :     }
    1152           0 :   rc = agent_scd_getattr ("KEY-FPR", info);
    1153           0 :   if (!rc)
    1154           0 :     rc = agent_scd_getattr ("CHV-STATUS", info);
    1155           0 :   if (!rc)
    1156           0 :     rc = agent_scd_getattr ("DISP-NAME", info);
    1157           0 :   if (!rc)
    1158           0 :     rc = agent_scd_getattr ("EXTCAP", info);
    1159           0 :   if (!rc)
    1160           0 :     rc = agent_scd_getattr ("KEY-ATTR", info);
    1161           0 :   if (rc)
    1162           0 :     log_error (_("error getting current key info: %s\n"), gpg_strerror (rc));
    1163           0 :   return rc;
    1164             : }
    1165             : 
    1166             : 
    1167             : /* Helper for the key generation/edit functions.  */
    1168             : static int
    1169           0 : check_pin_for_key_operation (struct agent_card_info_s *info, int *forced_chv1)
    1170             : {
    1171           0 :   int rc = 0;
    1172             : 
    1173           0 :   agent_clear_pin_cache (info->serialno);
    1174             : 
    1175           0 :   *forced_chv1 = !info->chv1_cached;
    1176           0 :   if (*forced_chv1)
    1177             :     { /* Switch off the forced mode so that during key generation we
    1178             :          don't get bothered with PIN queries for each
    1179             :          self-signature. */
    1180           0 :       rc = agent_scd_setattr ("CHV-STATUS-1", "\x01", 1, info->serialno);
    1181           0 :       if (rc)
    1182             :         {
    1183           0 :           log_error ("error clearing forced signature PIN flag: %s\n",
    1184             :                      gpg_strerror (rc));
    1185           0 :           *forced_chv1 = 0;
    1186             :         }
    1187             :     }
    1188             : 
    1189           0 :   if (!rc)
    1190             :     {
    1191             :       /* Check the PIN now, so that we won't get asked later for each
    1192             :          binding signature. */
    1193           0 :       rc = agent_scd_checkpin (info->serialno);
    1194           0 :       if (rc)
    1195             :         {
    1196           0 :           log_error ("error checking the PIN: %s\n", gpg_strerror (rc));
    1197           0 :           write_sc_op_status (rc);
    1198             :         }
    1199             :   }
    1200           0 :   return rc;
    1201             : }
    1202             : 
    1203             : /* Helper for the key generation/edit functions.  */
    1204             : static void
    1205           0 : restore_forced_chv1 (int *forced_chv1)
    1206             : {
    1207             :   int rc;
    1208             : 
    1209           0 :   if (*forced_chv1)
    1210             :     { /* Switch back to forced state. */
    1211           0 :       rc = agent_scd_setattr ("CHV-STATUS-1", "", 1, NULL);
    1212           0 :       if (rc)
    1213             :         {
    1214           0 :           log_error ("error setting forced signature PIN flag: %s\n",
    1215             :                      gpg_strerror (rc));
    1216             :         }
    1217             :     }
    1218           0 : }
    1219             : 
    1220             : 
    1221             : /* Helper for the key generation/edit functions.  */
    1222             : static void
    1223           0 : show_card_key_info (struct agent_card_info_s *info)
    1224             : {
    1225           0 :   tty_fprintf (NULL, "Signature key ....:");
    1226           0 :   print_sha1_fpr (NULL, info->fpr1valid? info->fpr1:NULL);
    1227           0 :   tty_fprintf (NULL, "Encryption key....:");
    1228           0 :   print_sha1_fpr (NULL, info->fpr2valid? info->fpr2:NULL);
    1229           0 :   tty_fprintf (NULL, "Authentication key:");
    1230           0 :   print_sha1_fpr (NULL, info->fpr3valid? info->fpr3:NULL);
    1231           0 :   tty_printf ("\n");
    1232           0 : }
    1233             : 
    1234             : 
    1235             : /* Helper for the key generation/edit functions.  */
    1236             : static int
    1237           0 : replace_existing_key_p (struct agent_card_info_s *info, int keyno)
    1238             : {
    1239           0 :   log_assert (keyno >= 0 && keyno <= 3);
    1240             : 
    1241           0 :   if ((keyno == 1 && info->fpr1valid)
    1242           0 :       || (keyno == 2 && info->fpr2valid)
    1243           0 :       || (keyno == 3 && info->fpr3valid))
    1244             :     {
    1245           0 :       tty_printf ("\n");
    1246           0 :       log_info ("WARNING: such a key has already been stored on the card!\n");
    1247           0 :       tty_printf ("\n");
    1248           0 :       if ( !cpr_get_answer_is_yes( "cardedit.genkeys.replace_key",
    1249           0 :                                   _("Replace existing key? (y/N) ")))
    1250           0 :         return -1;
    1251           0 :       return 1;
    1252             :     }
    1253           0 :   return 0;
    1254             : }
    1255             : 
    1256             : 
    1257             : static void
    1258           0 : show_keysize_warning (void)
    1259             : {
    1260             :   static int shown;
    1261             : 
    1262           0 :   if (shown)
    1263           0 :     return;
    1264           0 :   shown = 1;
    1265           0 :   tty_printf
    1266           0 :     (_("Note: There is no guarantee that the card "
    1267             :        "supports the requested size.\n"
    1268             :        "      If the key generation does not succeed, "
    1269             :        "please check the\n"
    1270             :        "      documentation of your card to see what "
    1271             :        "sizes are allowed.\n"));
    1272             : }
    1273             : 
    1274             : 
    1275             : /* Ask for the size of a card key.  NBITS is the current size
    1276             :    configured for the card.  KEYNO is the number of the key used to
    1277             :    select the prompt.  Returns 0 to use the default size (i.e. NBITS)
    1278             :    or the selected size.  */
    1279             : static unsigned int
    1280           0 : ask_card_keysize (int keyno, unsigned int nbits)
    1281             : {
    1282           0 :   unsigned int min_nbits = 1024;
    1283           0 :   unsigned int max_nbits = 4096;
    1284             :   char *prompt, *answer;
    1285             :   unsigned int req_nbits;
    1286             : 
    1287             :   for (;;)
    1288             :     {
    1289           0 :       prompt = xasprintf
    1290             :         (keyno == 0?
    1291             :          _("What keysize do you want for the Signature key? (%u) "):
    1292             :          keyno == 1?
    1293             :          _("What keysize do you want for the Encryption key? (%u) "):
    1294             :          _("What keysize do you want for the Authentication key? (%u) "),
    1295             :          nbits);
    1296           0 :       answer = cpr_get ("cardedit.genkeys.size", prompt);
    1297           0 :       cpr_kill_prompt ();
    1298           0 :       req_nbits = *answer? atoi (answer): nbits;
    1299           0 :       xfree (prompt);
    1300           0 :       xfree (answer);
    1301             : 
    1302           0 :       if (req_nbits != nbits && (req_nbits % 32) )
    1303             :         {
    1304           0 :           req_nbits = ((req_nbits + 31) / 32) * 32;
    1305           0 :           tty_printf (_("rounded up to %u bits\n"), req_nbits);
    1306             :         }
    1307             : 
    1308           0 :       if (req_nbits == nbits)
    1309           0 :         return 0;  /* Use default.  */
    1310             : 
    1311           0 :       if (req_nbits < min_nbits || req_nbits > max_nbits)
    1312             :         {
    1313           0 :           tty_printf (_("%s keysizes must be in the range %u-%u\n"),
    1314             :                       "RSA", min_nbits, max_nbits);
    1315             :         }
    1316             :       else
    1317             :         {
    1318           0 :           tty_printf (_("The card will now be re-configured "
    1319             :                         "to generate a key of %u bits\n"), req_nbits);
    1320           0 :           show_keysize_warning ();
    1321           0 :           return req_nbits;
    1322             :         }
    1323           0 :     }
    1324             : }
    1325             : 
    1326             : 
    1327             : /* Change the size of key KEYNO (0..2) to NBITS and show an error
    1328             :    message if that fails.  */
    1329             : static gpg_error_t
    1330           0 : do_change_keysize (int keyno, unsigned int nbits)
    1331             : {
    1332             :   gpg_error_t err;
    1333             :   char args[100];
    1334             : 
    1335           0 :   snprintf (args, sizeof args, "--force %d 1 rsa%u", keyno+1, nbits);
    1336           0 :   err = agent_scd_setattr ("KEY-ATTR", args, strlen (args), NULL);
    1337           0 :   if (err)
    1338           0 :     log_error (_("error changing size of key %d to %u bits: %s\n"),
    1339             :                keyno+1, nbits, gpg_strerror (err));
    1340           0 :   return err;
    1341             : }
    1342             : 
    1343             : 
    1344             : static void
    1345           0 : generate_card_keys (ctrl_t ctrl)
    1346             : {
    1347             :   struct agent_card_info_s info;
    1348             :   int forced_chv1;
    1349             :   int want_backup;
    1350             :   int keyno;
    1351             : 
    1352           0 :   if (get_info_for_key_operation (&info))
    1353           0 :     return;
    1354             : 
    1355           0 :   if (info.extcap.ki)
    1356             :     {
    1357             :       char *answer;
    1358             : 
    1359             :       /* FIXME: Should be something like cpr_get_bool so that a status
    1360             :          GET_BOOL will be emitted.  */
    1361           0 :       answer = cpr_get ("cardedit.genkeys.backup_enc",
    1362           0 :                         _("Make off-card backup of encryption key? (Y/n) "));
    1363             : 
    1364           0 :       want_backup = answer_is_yes_no_default (answer, 1/*(default to Yes)*/);
    1365           0 :       cpr_kill_prompt ();
    1366           0 :       xfree (answer);
    1367             :     }
    1368             :   else
    1369           0 :     want_backup = 0;
    1370             : 
    1371           0 :   if ( (info.fpr1valid && !fpr_is_zero (info.fpr1))
    1372           0 :        || (info.fpr2valid && !fpr_is_zero (info.fpr2))
    1373           0 :        || (info.fpr3valid && !fpr_is_zero (info.fpr3)))
    1374             :     {
    1375           0 :       tty_printf ("\n");
    1376           0 :       log_info (_("Note: keys are already stored on the card!\n"));
    1377           0 :       tty_printf ("\n");
    1378           0 :       if ( !cpr_get_answer_is_yes ("cardedit.genkeys.replace_keys",
    1379           0 :                                    _("Replace existing keys? (y/N) ")))
    1380             :         {
    1381           0 :           agent_release_card_info (&info);
    1382           0 :           return;
    1383             :         }
    1384             :     }
    1385             : 
    1386             :   /* If no displayed name has been set, we assume that this is a fresh
    1387             :      card and print a hint about the default PINs.  */
    1388           0 :   if (!info.disp_name || !*info.disp_name)
    1389             :     {
    1390           0 :       tty_printf ("\n");
    1391           0 :       tty_printf (_("Please note that the factory settings of the PINs are\n"
    1392             :                     "   PIN = '%s'     Admin PIN = '%s'\n"
    1393             :                     "You should change them using the command --change-pin\n"),
    1394             :                   "123456", "12345678");
    1395           0 :       tty_printf ("\n");
    1396             :     }
    1397             : 
    1398           0 :   if (check_pin_for_key_operation (&info, &forced_chv1))
    1399           0 :     goto leave;
    1400             : 
    1401             :   /* If the cards features changeable key attributes, we ask for the
    1402             :      key size.  */
    1403           0 :   if (info.is_v2 && info.extcap.aac)
    1404             :     {
    1405             :       unsigned int nbits;
    1406             : 
    1407           0 :       for (keyno = 0; keyno < DIM (info.key_attr); keyno++)
    1408             :         {
    1409           0 :           nbits = ask_card_keysize (keyno, info.key_attr[keyno].nbits);
    1410           0 :           if (nbits && do_change_keysize (keyno, nbits))
    1411             :             {
    1412             :               /* Error: Better read the default key size again.  */
    1413           0 :               agent_release_card_info (&info);
    1414           0 :               if (get_info_for_key_operation (&info))
    1415           0 :                 goto leave;
    1416             :               /* Ask again for this key size. */
    1417           0 :               keyno--;
    1418             :             }
    1419             :         }
    1420             :       /* Note that INFO has not be synced.  However we will only use
    1421             :          the serialnumber and thus it won't harm.  */
    1422             :     }
    1423             : 
    1424           0 :   generate_keypair (ctrl, 1, NULL, info.serialno, want_backup);
    1425             : 
    1426             :  leave:
    1427           0 :   agent_release_card_info (&info);
    1428           0 :   restore_forced_chv1 (&forced_chv1);
    1429             : }
    1430             : 
    1431             : 
    1432             : /* This function is used by the key edit menu to generate an arbitrary
    1433             :    subkey. */
    1434             : gpg_error_t
    1435           0 : card_generate_subkey (KBNODE pub_keyblock)
    1436             : {
    1437             :   gpg_error_t err;
    1438             :   struct agent_card_info_s info;
    1439           0 :   int forced_chv1 = 0;
    1440             :   int keyno;
    1441             : 
    1442           0 :   err = get_info_for_key_operation (&info);
    1443           0 :   if (err)
    1444           0 :     return err;
    1445             : 
    1446           0 :   show_card_key_info (&info);
    1447             : 
    1448           0 :   tty_printf (_("Please select the type of key to generate:\n"));
    1449             : 
    1450           0 :   tty_printf (_("   (1) Signature key\n"));
    1451           0 :   tty_printf (_("   (2) Encryption key\n"));
    1452           0 :   tty_printf (_("   (3) Authentication key\n"));
    1453             : 
    1454             :   for (;;)
    1455             :     {
    1456           0 :       char *answer = cpr_get ("cardedit.genkeys.subkeytype",
    1457           0 :                               _("Your selection? "));
    1458           0 :       cpr_kill_prompt();
    1459           0 :       if (*answer == CONTROL_D)
    1460             :         {
    1461           0 :           xfree (answer);
    1462           0 :           err = gpg_error (GPG_ERR_CANCELED);
    1463           0 :           goto leave;
    1464             :         }
    1465           0 :       keyno = *answer? atoi(answer): 0;
    1466           0 :       xfree(answer);
    1467           0 :       if (keyno >= 1 && keyno <= 3)
    1468           0 :         break; /* Okay. */
    1469           0 :       tty_printf(_("Invalid selection.\n"));
    1470           0 :     }
    1471             : 
    1472           0 :   if (replace_existing_key_p (&info, keyno) < 0)
    1473             :     {
    1474           0 :       err = gpg_error (GPG_ERR_CANCELED);
    1475           0 :       goto leave;
    1476             :     }
    1477             : 
    1478           0 :   err = check_pin_for_key_operation (&info, &forced_chv1);
    1479           0 :   if (err)
    1480           0 :     goto leave;
    1481             : 
    1482             :   /* If the cards features changeable key attributes, we ask for the
    1483             :      key size.  */
    1484           0 :   if (info.is_v2 && info.extcap.aac)
    1485             :     {
    1486             :       unsigned int nbits;
    1487             : 
    1488             :     ask_again:
    1489           0 :       nbits = ask_card_keysize (keyno-1, info.key_attr[keyno-1].nbits);
    1490           0 :       if (nbits && do_change_keysize (keyno-1, nbits))
    1491             :         {
    1492             :           /* Error: Better read the default key size again.  */
    1493           0 :           agent_release_card_info (&info);
    1494           0 :           err = get_info_for_key_operation (&info);
    1495           0 :           if (err)
    1496           0 :             goto leave;
    1497           0 :           goto ask_again;
    1498             :         }
    1499             :       /* Note that INFO has not be synced.  However we will only use
    1500             :          the serialnumber and thus it won't harm.  */
    1501             :     }
    1502             : 
    1503           0 :   err = generate_card_subkeypair (pub_keyblock, keyno, info.serialno);
    1504             : 
    1505             :  leave:
    1506           0 :   agent_release_card_info (&info);
    1507           0 :   restore_forced_chv1 (&forced_chv1);
    1508           0 :   return err;
    1509             : }
    1510             : 
    1511             : 
    1512             : /* Store the key at NODE into the smartcard and modify NODE to
    1513             :    carry the serialno stuff instead of the actual secret key
    1514             :    parameters.  USE is the usage for that key; 0 means any
    1515             :    usage. */
    1516             : int
    1517           0 : card_store_subkey (KBNODE node, int use)
    1518             : {
    1519             :   struct agent_card_info_s info;
    1520           0 :   int okay = 0;
    1521             :   unsigned int nbits;
    1522             :   int allow_keyno[3];
    1523             :   int  keyno;
    1524             :   PKT_public_key *pk;
    1525             :   gpg_error_t err;
    1526             :   char *hexgrip;
    1527             :   int rc;
    1528             :   gnupg_isotime_t timebuf;
    1529             : 
    1530           0 :   log_assert (node->pkt->pkttype == PKT_PUBLIC_KEY
    1531             :               || node->pkt->pkttype == PKT_PUBLIC_SUBKEY);
    1532             : 
    1533           0 :   pk = node->pkt->pkt.public_key;
    1534             : 
    1535           0 :   if (get_info_for_key_operation (&info))
    1536           0 :     return 0;
    1537             : 
    1538           0 :   if (!info.extcap.ki)
    1539             :     {
    1540           0 :       tty_printf ("The card does not support the import of keys\n");
    1541           0 :       tty_printf ("\n");
    1542           0 :       goto leave;
    1543             :     }
    1544             : 
    1545           0 :   nbits = nbits_from_pk (pk);
    1546             : 
    1547           0 :   if (!info.is_v2 && nbits != 1024)
    1548             :     {
    1549           0 :       tty_printf ("You may only store a 1024 bit RSA key on the card\n");
    1550           0 :       tty_printf ("\n");
    1551           0 :       goto leave;
    1552             :     }
    1553             : 
    1554           0 :   allow_keyno[0] = (!use || (use & (PUBKEY_USAGE_SIG|PUBKEY_USAGE_CERT)));
    1555           0 :   allow_keyno[1] = (!use || (use & (PUBKEY_USAGE_ENC)));
    1556           0 :   allow_keyno[2] = (!use || (use & (PUBKEY_USAGE_SIG|PUBKEY_USAGE_AUTH)));
    1557             : 
    1558           0 :   tty_printf (_("Please select where to store the key:\n"));
    1559             : 
    1560           0 :   if (allow_keyno[0])
    1561           0 :     tty_printf (_("   (1) Signature key\n"));
    1562           0 :   if (allow_keyno[1])
    1563           0 :     tty_printf (_("   (2) Encryption key\n"));
    1564           0 :   if (allow_keyno[2])
    1565           0 :     tty_printf (_("   (3) Authentication key\n"));
    1566             : 
    1567             :   for (;;)
    1568             :     {
    1569           0 :       char *answer = cpr_get ("cardedit.genkeys.storekeytype",
    1570           0 :                               _("Your selection? "));
    1571           0 :       cpr_kill_prompt();
    1572           0 :       if (*answer == CONTROL_D || !*answer)
    1573             :         {
    1574           0 :           xfree (answer);
    1575           0 :           goto leave;
    1576             :         }
    1577           0 :       keyno = *answer? atoi(answer): 0;
    1578           0 :       xfree(answer);
    1579           0 :       if (keyno >= 1 && keyno <= 3 && allow_keyno[keyno-1])
    1580             :         {
    1581           0 :           if (info.is_v2 && !info.extcap.aac
    1582           0 :               && info.key_attr[keyno-1].nbits != nbits)
    1583             :             {
    1584           0 :               tty_printf ("Key does not match the card's capability.\n");
    1585             :             }
    1586             :           else
    1587             :             break; /* Okay. */
    1588             :         }
    1589             :       else
    1590           0 :         tty_printf(_("Invalid selection.\n"));
    1591           0 :     }
    1592             : 
    1593           0 :   if ((rc = replace_existing_key_p (&info, keyno)) < 0)
    1594           0 :     goto leave;
    1595             : 
    1596           0 :   err = hexkeygrip_from_pk (pk, &hexgrip);
    1597           0 :   if (err)
    1598           0 :     goto leave;
    1599             : 
    1600           0 :   epoch2isotime (timebuf, (time_t)pk->timestamp);
    1601           0 :   rc = agent_keytocard (hexgrip, keyno, rc, info.serialno, timebuf);
    1602             : 
    1603           0 :   if (rc)
    1604           0 :     log_error (_("KEYTOCARD failed: %s\n"), gpg_strerror (rc));
    1605             :   else
    1606           0 :     okay = 1;
    1607           0 :   xfree (hexgrip);
    1608             : 
    1609             :  leave:
    1610           0 :   agent_release_card_info (&info);
    1611           0 :   return okay;
    1612             : }
    1613             : 
    1614             : 
    1615             : 
    1616             : /* Direct sending of an hex encoded APDU with error printing.  */
    1617             : static gpg_error_t
    1618           0 : send_apdu (const char *hexapdu, const char *desc, unsigned int ignore)
    1619             : {
    1620             :   gpg_error_t err;
    1621             :   unsigned int sw;
    1622             : 
    1623           0 :   err = agent_scd_apdu (hexapdu, &sw);
    1624           0 :   if (err)
    1625           0 :     tty_printf ("sending card command %s failed: %s\n", desc,
    1626             :                 gpg_strerror (err));
    1627           0 :   else if (!hexapdu || !strcmp (hexapdu, "undefined"))
    1628             :     ;
    1629           0 :   else if (ignore == 0xffff)
    1630             :     ; /* Ignore all status words.  */
    1631           0 :   else if (sw != 0x9000)
    1632             :     {
    1633           0 :       switch (sw)
    1634             :         {
    1635           0 :         case 0x6285: err = gpg_error (GPG_ERR_OBJ_TERM_STATE); break;
    1636           0 :         case 0x6982: err = gpg_error (GPG_ERR_BAD_PIN); break;
    1637           0 :         case 0x6985: err = gpg_error (GPG_ERR_USE_CONDITIONS); break;
    1638           0 :         default: err = gpg_error (GPG_ERR_CARD);
    1639             :         }
    1640           0 :       if (!(ignore && ignore == sw))
    1641           0 :         tty_printf ("card command %s failed: %s (0x%04x)\n", desc,
    1642             :                     gpg_strerror (err),  sw);
    1643             :     }
    1644           0 :   return err;
    1645             : }
    1646             : 
    1647             : 
    1648             : /* Do a factory reset after confirmation.  */
    1649             : static void
    1650           0 : factory_reset (void)
    1651             : {
    1652             :   struct agent_card_info_s info;
    1653             :   gpg_error_t err;
    1654           0 :   char *answer = NULL;
    1655           0 :   int termstate = 0;
    1656             :   int i;
    1657             : 
    1658             :   /*  The code below basically does the same what this
    1659             :       gpg-connect-agent script does:
    1660             : 
    1661             :         scd reset
    1662             :         scd serialno undefined
    1663             :         scd apdu 00 A4 04 00 06 D2 76 00 01 24 01
    1664             :         scd apdu 00 20 00 81 08 40 40 40 40 40 40 40 40
    1665             :         scd apdu 00 20 00 81 08 40 40 40 40 40 40 40 40
    1666             :         scd apdu 00 20 00 81 08 40 40 40 40 40 40 40 40
    1667             :         scd apdu 00 20 00 81 08 40 40 40 40 40 40 40 40
    1668             :         scd apdu 00 20 00 83 08 40 40 40 40 40 40 40 40
    1669             :         scd apdu 00 20 00 83 08 40 40 40 40 40 40 40 40
    1670             :         scd apdu 00 20 00 83 08 40 40 40 40 40 40 40 40
    1671             :         scd apdu 00 20 00 83 08 40 40 40 40 40 40 40 40
    1672             :         scd apdu 00 e6 00 00
    1673             :         scd reset
    1674             :         scd serialno undefined
    1675             :         scd apdu 00 A4 04 00 06 D2 76 00 01 24 01
    1676             :         scd apdu 00 44 00 00
    1677             :         /echo Card has been reset to factory defaults
    1678             : 
    1679             :       but tries to find out something about the card first.
    1680             :    */
    1681             : 
    1682           0 :   err = agent_scd_learn (&info, 0);
    1683           0 :   if (gpg_err_code (err) == GPG_ERR_OBJ_TERM_STATE
    1684           0 :       && gpg_err_source (err) == GPG_ERR_SOURCE_SCD)
    1685           0 :     termstate = 1;
    1686           0 :   else if (err)
    1687             :     {
    1688           0 :       log_error (_("OpenPGP card not available: %s\n"), gpg_strerror (err));
    1689           0 :       return;
    1690             :     }
    1691             : 
    1692           0 :   if (!termstate)
    1693             :     {
    1694           0 :       log_info (_("OpenPGP card no. %s detected\n"),
    1695           0 :                 info.serialno? info.serialno : "[none]");
    1696           0 :       if (!(info.status_indicator == 3 || info.status_indicator == 5))
    1697             :         {
    1698             :           /* Note: We won't see status-indicator 3 here because it is not
    1699             :              possible to select a card application in termination state.  */
    1700           0 :           log_error (_("This command is not supported by this card\n"));
    1701           0 :           goto leave;
    1702             :         }
    1703             : 
    1704           0 :       tty_printf ("\n");
    1705           0 :       log_info (_("Note: This command destroys all keys stored on the card!\n"));
    1706           0 :       tty_printf ("\n");
    1707           0 :       if (!cpr_get_answer_is_yes ("cardedit.factory-reset.proceed",
    1708           0 :                                   _("Continue? (y/N) ")))
    1709           0 :         goto leave;
    1710             : 
    1711             : 
    1712           0 :       answer = cpr_get ("cardedit.factory-reset.really",
    1713           0 :                         _("Really do a factory reset? (enter \"yes\") "));
    1714           0 :       cpr_kill_prompt ();
    1715           0 :       trim_spaces (answer);
    1716           0 :       if (strcmp (answer, "yes"))
    1717           0 :         goto leave;
    1718             : 
    1719             :       /* We need to select a card application before we can send APDUs
    1720             :          to the card without scdaemon doing anything on its own.  */
    1721           0 :       err = send_apdu (NULL, "RESET", 0);
    1722           0 :       if (err)
    1723           0 :         goto leave;
    1724           0 :       err = send_apdu ("undefined", "dummy select ", 0);
    1725           0 :       if (err)
    1726           0 :         goto leave;
    1727             : 
    1728             :       /* Select the OpenPGP application.  */
    1729           0 :       err = send_apdu ("00A4040006D27600012401", "SELECT AID", 0);
    1730           0 :       if (err)
    1731           0 :         goto leave;
    1732             : 
    1733             :       /* Do some dummy verifies with wrong PINs to set the retry
    1734             :          counter to zero.  We can't easily use the card version 2.1
    1735             :          feature of presenting the admin PIN to allow the terminate
    1736             :          command because there is no machinery in scdaemon to catch
    1737             :          the verify command and ask for the PIN when the "APDU"
    1738             :          command is used. */
    1739           0 :       for (i=0; i < 4; i++)
    1740           0 :         send_apdu ("00200081084040404040404040", "VERIFY", 0xffff);
    1741           0 :       for (i=0; i < 4; i++)
    1742           0 :         send_apdu ("00200083084040404040404040", "VERIFY", 0xffff);
    1743             : 
    1744             :       /* Send terminate datafile command.  */
    1745           0 :       err = send_apdu ("00e60000", "TERMINATE DF", 0x6985);
    1746           0 :       if (err)
    1747           0 :         goto leave;
    1748             :     }
    1749             : 
    1750             :   /* The card is in termination state - reset and select again.  */
    1751           0 :   err = send_apdu (NULL, "RESET", 0);
    1752           0 :   if (err)
    1753           0 :     goto leave;
    1754           0 :   err = send_apdu ("undefined", "dummy select", 0);
    1755           0 :   if (err)
    1756           0 :     goto leave;
    1757             : 
    1758             :   /* Select the OpenPGP application. (no error checking here). */
    1759           0 :   send_apdu ("00A4040006D27600012401", "SELECT AID", 0xffff);
    1760             : 
    1761             :   /* Send activate datafile command.  This is used without
    1762             :      confirmation if the card is already in termination state.  */
    1763           0 :   err = send_apdu ("00440000", "ACTIVATE DF", 0);
    1764           0 :   if (err)
    1765           0 :     goto leave;
    1766             : 
    1767             :   /* Finally we reset the card reader once more.  */
    1768           0 :   err = send_apdu (NULL, "RESET", 0);
    1769           0 :   if (err)
    1770           0 :     goto leave;
    1771             : 
    1772             :  leave:
    1773           0 :   xfree (answer);
    1774           0 :   agent_release_card_info (&info);
    1775             : }
    1776             : 
    1777             : 
    1778             : 
    1779             : /* Data used by the command parser.  This needs to be outside of the
    1780             :    function scope to allow readline based command completion.  */
    1781             : enum cmdids
    1782             :   {
    1783             :     cmdNOP = 0,
    1784             :     cmdQUIT, cmdADMIN, cmdHELP, cmdLIST, cmdDEBUG, cmdVERIFY,
    1785             :     cmdNAME, cmdURL, cmdFETCH, cmdLOGIN, cmdLANG, cmdSEX, cmdCAFPR,
    1786             :     cmdFORCESIG, cmdGENERATE, cmdPASSWD, cmdPRIVATEDO, cmdWRITECERT,
    1787             :     cmdREADCERT, cmdUNBLOCK, cmdFACTORYRESET,
    1788             :     cmdINVCMD
    1789             :   };
    1790             : 
    1791             : static struct
    1792             : {
    1793             :   const char *name;
    1794             :   enum cmdids id;
    1795             :   int admin_only;
    1796             :   const char *desc;
    1797             : } cmds[] =
    1798             :   {
    1799             :     { "quit"    , cmdQUIT  , 0, N_("quit this menu")},
    1800             :     { "q"       , cmdQUIT  , 0, NULL },
    1801             :     { "admin"   , cmdADMIN , 0, N_("show admin commands")},
    1802             :     { "help"    , cmdHELP  , 0, N_("show this help")},
    1803             :     { "?"       , cmdHELP  , 0, NULL },
    1804             :     { "list"    , cmdLIST  , 0, N_("list all available data")},
    1805             :     { "l"       , cmdLIST  , 0, NULL },
    1806             :     { "debug"   , cmdDEBUG , 0, NULL },
    1807             :     { "name"    , cmdNAME  , 1, N_("change card holder's name")},
    1808             :     { "url"     , cmdURL   , 1, N_("change URL to retrieve key")},
    1809             :     { "fetch"   , cmdFETCH , 0, N_("fetch the key specified in the card URL")},
    1810             :     { "login"   , cmdLOGIN , 1, N_("change the login name")},
    1811             :     { "lang"    , cmdLANG  , 1, N_("change the language preferences")},
    1812             :     { "sex"     , cmdSEX   , 1, N_("change card holder's sex")},
    1813             :     { "cafpr"   , cmdCAFPR , 1, N_("change a CA fingerprint")},
    1814             :     { "forcesig", cmdFORCESIG, 1, N_("toggle the signature force PIN flag")},
    1815             :     { "generate", cmdGENERATE, 1, N_("generate new keys")},
    1816             :     { "passwd"  , cmdPASSWD, 0, N_("menu to change or unblock the PIN")},
    1817             :     { "verify"  , cmdVERIFY, 0, N_("verify the PIN and list all data")},
    1818             :     { "unblock" , cmdUNBLOCK,0, N_("unblock the PIN using a Reset Code") },
    1819             :     { "factory-reset", cmdFACTORYRESET, 1, N_("destroy all keys and data")},
    1820             :     /* Note, that we do not announce these command yet. */
    1821             :     { "privatedo", cmdPRIVATEDO, 0, NULL },
    1822             :     { "readcert", cmdREADCERT, 0, NULL },
    1823             :     { "writecert", cmdWRITECERT, 1, NULL },
    1824             :     { NULL, cmdINVCMD, 0, NULL }
    1825             :   };
    1826             : 
    1827             : 
    1828             : #ifdef HAVE_LIBREADLINE
    1829             : 
    1830             : /* These two functions are used by readline for command completion. */
    1831             : 
    1832             : static char *
    1833           0 : command_generator(const char *text,int state)
    1834             : {
    1835             :   static int list_index,len;
    1836             :   const char *name;
    1837             : 
    1838             :   /* If this is a new word to complete, initialize now.  This includes
    1839             :      saving the length of TEXT for efficiency, and initializing the
    1840             :      index variable to 0. */
    1841           0 :   if(!state)
    1842             :     {
    1843           0 :       list_index=0;
    1844           0 :       len=strlen(text);
    1845             :     }
    1846             : 
    1847             :   /* Return the next partial match */
    1848           0 :   while((name=cmds[list_index].name))
    1849             :     {
    1850             :       /* Only complete commands that have help text */
    1851           0 :       if(cmds[list_index++].desc && strncmp(name,text,len)==0)
    1852           0 :         return strdup(name);
    1853             :     }
    1854             : 
    1855           0 :   return NULL;
    1856             : }
    1857             : 
    1858             : static char **
    1859           0 : card_edit_completion(const char *text, int start, int end)
    1860             : {
    1861             :   (void)end;
    1862             :   /* If we are at the start of a line, we try and command-complete.
    1863             :      If not, just do nothing for now. */
    1864             : 
    1865           0 :   if(start==0)
    1866           0 :     return rl_completion_matches(text,command_generator);
    1867             : 
    1868           0 :   rl_attempted_completion_over=1;
    1869             : 
    1870           0 :   return NULL;
    1871             : }
    1872             : #endif /*HAVE_LIBREADLINE*/
    1873             : 
    1874             : /* Menu to edit all user changeable values on an OpenPGP card.  Only
    1875             :    Key creation is not handled here. */
    1876             : void
    1877           0 : card_edit (ctrl_t ctrl, strlist_t commands)
    1878             : {
    1879           0 :   enum cmdids cmd = cmdNOP;
    1880           0 :   int have_commands = !!commands;
    1881           0 :   int redisplay = 1;
    1882           0 :   char *answer = NULL;
    1883           0 :   int allow_admin=0;
    1884             :   char serialnobuf[50];
    1885             : 
    1886             : 
    1887           0 :   if (opt.command_fd != -1)
    1888             :     ;
    1889           0 :   else if (opt.batch && !have_commands)
    1890             :     {
    1891           0 :       log_error(_("can't do this in batch mode\n"));
    1892           0 :       goto leave;
    1893             :     }
    1894             : 
    1895             :   for (;;)
    1896             :     {
    1897             :       int arg_number;
    1898           0 :       const char *arg_string = "";
    1899           0 :       const char *arg_rest = "";
    1900             :       char *p;
    1901             :       int i;
    1902             :       int cmd_admin_only;
    1903             : 
    1904           0 :       tty_printf("\n");
    1905           0 :       if (redisplay )
    1906             :         {
    1907           0 :           if (opt.with_colons)
    1908             :             {
    1909           0 :               card_status (es_stdout, serialnobuf, DIM (serialnobuf));
    1910           0 :               fflush (stdout);
    1911             :             }
    1912             :           else
    1913             :             {
    1914           0 :               card_status (NULL, serialnobuf, DIM (serialnobuf));
    1915           0 :               tty_printf("\n");
    1916             :             }
    1917           0 :           redisplay = 0;
    1918             :         }
    1919             : 
    1920             :       do
    1921             :         {
    1922           0 :           xfree (answer);
    1923           0 :           if (have_commands)
    1924             :             {
    1925           0 :               if (commands)
    1926             :                 {
    1927           0 :                   answer = xstrdup (commands->d);
    1928           0 :                   commands = commands->next;
    1929             :                 }
    1930           0 :               else if (opt.batch)
    1931             :                 {
    1932           0 :                   answer = xstrdup ("quit");
    1933             :                 }
    1934             :               else
    1935           0 :                 have_commands = 0;
    1936             :             }
    1937             : 
    1938           0 :             if (!have_commands)
    1939             :               {
    1940           0 :                 tty_enable_completion (card_edit_completion);
    1941           0 :                 answer = cpr_get_no_help("cardedit.prompt", _("gpg/card> "));
    1942           0 :                 cpr_kill_prompt();
    1943           0 :                 tty_disable_completion ();
    1944             :               }
    1945           0 :             trim_spaces(answer);
    1946             :         }
    1947           0 :       while ( *answer == '#' );
    1948             : 
    1949           0 :       arg_number = 0; /* Yes, here is the init which egcc complains about */
    1950           0 :       cmd_admin_only = 0;
    1951           0 :       if (!*answer)
    1952           0 :         cmd = cmdLIST; /* Default to the list command */
    1953           0 :       else if (*answer == CONTROL_D)
    1954           0 :         cmd = cmdQUIT;
    1955             :       else
    1956             :         {
    1957           0 :           if ((p=strchr (answer,' ')))
    1958             :             {
    1959           0 :               *p++ = 0;
    1960           0 :               trim_spaces (answer);
    1961           0 :               trim_spaces (p);
    1962           0 :               arg_number = atoi(p);
    1963           0 :               arg_string = p;
    1964           0 :               arg_rest = p;
    1965           0 :               while (digitp (arg_rest))
    1966           0 :                 arg_rest++;
    1967           0 :               while (spacep (arg_rest))
    1968           0 :                 arg_rest++;
    1969             :             }
    1970             : 
    1971           0 :           for (i=0; cmds[i].name; i++ )
    1972           0 :             if (!ascii_strcasecmp (answer, cmds[i].name ))
    1973           0 :               break;
    1974             : 
    1975           0 :           cmd = cmds[i].id;
    1976           0 :           cmd_admin_only = cmds[i].admin_only;
    1977             :         }
    1978             : 
    1979           0 :       if (!allow_admin && cmd_admin_only)
    1980             :         {
    1981           0 :           tty_printf ("\n");
    1982           0 :           tty_printf (_("Admin-only command\n"));
    1983           0 :           continue;
    1984             :         }
    1985             : 
    1986           0 :       switch (cmd)
    1987             :         {
    1988             :         case cmdHELP:
    1989           0 :           for (i=0; cmds[i].name; i++ )
    1990           0 :             if(cmds[i].desc
    1991           0 :                && (!cmds[i].admin_only || (cmds[i].admin_only && allow_admin)))
    1992           0 :               tty_printf("%-14s %s\n", cmds[i].name, _(cmds[i].desc) );
    1993           0 :           break;
    1994             : 
    1995             :         case cmdADMIN:
    1996           0 :           if ( !strcmp (arg_string, "on") )
    1997           0 :             allow_admin = 1;
    1998           0 :           else if ( !strcmp (arg_string, "off") )
    1999           0 :             allow_admin = 0;
    2000           0 :           else if ( !strcmp (arg_string, "verify") )
    2001             :             {
    2002             :               /* Force verification of the Admin Command.  However,
    2003             :                  this is only done if the retry counter is at initial
    2004             :                  state.  */
    2005           0 :               char *tmp = xmalloc (strlen (serialnobuf) + 6 + 1);
    2006           0 :               strcpy (stpcpy (tmp, serialnobuf), "[CHV3]");
    2007           0 :               allow_admin = !agent_scd_checkpin (tmp);
    2008           0 :               xfree (tmp);
    2009             :             }
    2010             :           else /* Toggle. */
    2011           0 :             allow_admin=!allow_admin;
    2012           0 :           if(allow_admin)
    2013           0 :             tty_printf(_("Admin commands are allowed\n"));
    2014             :           else
    2015           0 :             tty_printf(_("Admin commands are not allowed\n"));
    2016           0 :           break;
    2017             : 
    2018             :         case cmdVERIFY:
    2019           0 :           agent_scd_checkpin (serialnobuf);
    2020           0 :           redisplay = 1;
    2021           0 :           break;
    2022             : 
    2023             :         case cmdLIST:
    2024           0 :           redisplay = 1;
    2025           0 :           break;
    2026             : 
    2027             :         case cmdNAME:
    2028           0 :           change_name ();
    2029           0 :           break;
    2030             : 
    2031             :         case cmdURL:
    2032           0 :           change_url ();
    2033           0 :           break;
    2034             : 
    2035             :         case cmdFETCH:
    2036           0 :           fetch_url (ctrl);
    2037           0 :           break;
    2038             : 
    2039             :         case cmdLOGIN:
    2040           0 :           change_login (arg_string);
    2041           0 :           break;
    2042             : 
    2043             :         case cmdLANG:
    2044           0 :           change_lang ();
    2045           0 :           break;
    2046             : 
    2047             :         case cmdSEX:
    2048           0 :           change_sex ();
    2049           0 :           break;
    2050             : 
    2051             :         case cmdCAFPR:
    2052           0 :           if ( arg_number < 1 || arg_number > 3 )
    2053           0 :             tty_printf ("usage: cafpr N\n"
    2054             :                         "       1 <= N <= 3\n");
    2055             :           else
    2056           0 :             change_cafpr (arg_number);
    2057           0 :           break;
    2058             : 
    2059             :         case cmdPRIVATEDO:
    2060           0 :           if ( arg_number < 1 || arg_number > 4 )
    2061           0 :             tty_printf ("usage: privatedo N\n"
    2062             :                         "       1 <= N <= 4\n");
    2063             :           else
    2064           0 :             change_private_do (arg_string, arg_number);
    2065           0 :           break;
    2066             : 
    2067             :         case cmdWRITECERT:
    2068           0 :           if ( arg_number != 3 )
    2069           0 :             tty_printf ("usage: writecert 3 < FILE\n");
    2070             :           else
    2071           0 :             change_cert (arg_rest);
    2072           0 :           break;
    2073             : 
    2074             :         case cmdREADCERT:
    2075           0 :           if ( arg_number != 3 )
    2076           0 :             tty_printf ("usage: readcert 3 > FILE\n");
    2077             :           else
    2078           0 :             read_cert (arg_rest);
    2079           0 :           break;
    2080             : 
    2081             :         case cmdFORCESIG:
    2082           0 :           toggle_forcesig ();
    2083           0 :           break;
    2084             : 
    2085             :         case cmdGENERATE:
    2086           0 :           generate_card_keys (ctrl);
    2087           0 :           break;
    2088             : 
    2089             :         case cmdPASSWD:
    2090           0 :           change_pin (0, allow_admin);
    2091           0 :           break;
    2092             : 
    2093             :         case cmdUNBLOCK:
    2094           0 :           change_pin (1, allow_admin);
    2095           0 :           break;
    2096             : 
    2097             :         case cmdFACTORYRESET:
    2098           0 :           factory_reset ();
    2099           0 :           break;
    2100             : 
    2101             :         case cmdQUIT:
    2102           0 :           goto leave;
    2103             : 
    2104             :         case cmdNOP:
    2105           0 :           break;
    2106             : 
    2107             :         case cmdINVCMD:
    2108             :         default:
    2109           0 :           tty_printf ("\n");
    2110           0 :           tty_printf (_("Invalid command  (try \"help\")\n"));
    2111           0 :           break;
    2112             :         } /* End command switch. */
    2113           0 :     } /* End of main menu loop. */
    2114             : 
    2115             :  leave:
    2116           0 :   xfree (answer);
    2117           0 : }

Generated by: LCOV version 1.11