LCOV - code coverage report
Current view: top level - g10 - call-agent.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 298 991 30.1 %
Date: 2016-12-01 18:37:21 Functions: 20 50 40.0 %

          Line data    Source code
       1             : /* call-agent.c - Divert GPG operations to the agent.
       2             :  * Copyright (C) 2001-2003, 2006-2011, 2013 Free Software Foundation, Inc.
       3             :  * Copyright (C) 2013-2015  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 <https://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             : #include <unistd.h>
      27             : #include <time.h>
      28             : #ifdef HAVE_LOCALE_H
      29             : #include <locale.h>
      30             : #endif
      31             : 
      32             : #include "gpg.h"
      33             : #include <assuan.h>
      34             : #include "util.h"
      35             : #include "membuf.h"
      36             : #include "options.h"
      37             : #include "i18n.h"
      38             : #include "asshelp.h"
      39             : #include "sysutils.h"
      40             : #include "call-agent.h"
      41             : #include "status.h"
      42             : #include "../common/shareddefs.h"
      43             : #include "host2net.h"
      44             : 
      45             : #define CONTROL_D ('D' - 'A' + 1)
      46             : 
      47             : 
      48             : static assuan_context_t agent_ctx = NULL;
      49             : static int did_early_card_test;
      50             : 
      51             : struct default_inq_parm_s
      52             : {
      53             :   ctrl_t ctrl;
      54             :   assuan_context_t ctx;
      55             :   struct {
      56             :     u32 *keyid;
      57             :     u32 *mainkeyid;
      58             :     int pubkey_algo;
      59             :   } keyinfo;
      60             : };
      61             : 
      62             : struct cipher_parm_s
      63             : {
      64             :   struct default_inq_parm_s *dflt;
      65             :   assuan_context_t ctx;
      66             :   unsigned char *ciphertext;
      67             :   size_t ciphertextlen;
      68             : };
      69             : 
      70             : struct writecert_parm_s
      71             : {
      72             :   struct default_inq_parm_s *dflt;
      73             :   const unsigned char *certdata;
      74             :   size_t certdatalen;
      75             : };
      76             : 
      77             : struct writekey_parm_s
      78             : {
      79             :   struct default_inq_parm_s *dflt;
      80             :   const unsigned char *keydata;
      81             :   size_t keydatalen;
      82             : };
      83             : 
      84             : struct genkey_parm_s
      85             : {
      86             :   struct default_inq_parm_s *dflt;
      87             :   const char *keyparms;
      88             :   const char *passphrase;
      89             : };
      90             : 
      91             : struct import_key_parm_s
      92             : {
      93             :   struct default_inq_parm_s *dflt;
      94             :   const void *key;
      95             :   size_t keylen;
      96             : };
      97             : 
      98             : 
      99             : struct cache_nonce_parm_s
     100             : {
     101             :   char **cache_nonce_addr;
     102             :   char **passwd_nonce_addr;
     103             : };
     104             : 
     105             : 
     106             : static gpg_error_t learn_status_cb (void *opaque, const char *line);
     107             : 
     108             : 
     109             : 
     110             : /* If RC is not 0, write an appropriate status message. */
     111             : static void
     112           0 : status_sc_op_failure (int rc)
     113             : {
     114           0 :   switch (gpg_err_code (rc))
     115             :     {
     116             :     case 0:
     117           0 :       break;
     118             :     case GPG_ERR_CANCELED:
     119             :     case GPG_ERR_FULLY_CANCELED:
     120           0 :       write_status_text (STATUS_SC_OP_FAILURE, "1");
     121           0 :       break;
     122             :     case GPG_ERR_BAD_PIN:
     123           0 :       write_status_text (STATUS_SC_OP_FAILURE, "2");
     124           0 :       break;
     125             :     default:
     126           0 :       write_status (STATUS_SC_OP_FAILURE);
     127           0 :       break;
     128             :     }
     129           0 : }
     130             : 
     131             : 
     132             : /* This is the default inquiry callback.  It mainly handles the
     133             :    Pinentry notifications.  */
     134             : static gpg_error_t
     135           5 : default_inq_cb (void *opaque, const char *line)
     136             : {
     137           5 :   gpg_error_t err = 0;
     138           5 :   struct default_inq_parm_s *parm = opaque;
     139             : 
     140           5 :   if (has_leading_keyword (line, "PINENTRY_LAUNCHED"))
     141             :     {
     142           5 :       err = gpg_proxy_pinentry_notify (parm->ctrl, line);
     143           5 :       if (err)
     144           0 :         log_error (_("failed to proxy %s inquiry to client\n"),
     145             :                    "PINENTRY_LAUNCHED");
     146             :       /* We do not pass errors to avoid breaking other code.  */
     147             :     }
     148           0 :   else if ((has_leading_keyword (line, "PASSPHRASE")
     149           0 :             || has_leading_keyword (line, "NEW_PASSPHRASE"))
     150           0 :            && opt.pinentry_mode == PINENTRY_MODE_LOOPBACK)
     151             :     {
     152           0 :       if (have_static_passphrase ())
     153             :         {
     154           0 :           const char *s = get_static_passphrase ();
     155           0 :           err = assuan_send_data (parm->ctx, s, strlen (s));
     156             :         }
     157             :       else
     158             :         {
     159             :           char *pw;
     160             :           char buf[32];
     161             : 
     162           0 :           if (parm->keyinfo.keyid)
     163           0 :             emit_status_need_passphrase (parm->keyinfo.keyid,
     164             :                                          parm->keyinfo.mainkeyid,
     165             :                                          parm->keyinfo.pubkey_algo);
     166             : 
     167           0 :           snprintf (buf, sizeof (buf), "%u", 100);
     168           0 :           write_status_text (STATUS_INQUIRE_MAXLEN, buf);
     169           0 :           pw = cpr_get_hidden ("passphrase.enter", _("Enter passphrase: "));
     170           0 :           cpr_kill_prompt ();
     171           0 :           if (*pw == CONTROL_D && !pw[1])
     172           0 :             err = gpg_error (GPG_ERR_CANCELED);
     173             :           else
     174           0 :             err = assuan_send_data (parm->ctx, pw, strlen (pw));
     175           0 :           xfree (pw);
     176             :         }
     177             :     }
     178             :   else
     179           0 :     log_debug ("ignoring gpg-agent inquiry '%s'\n", line);
     180             : 
     181           5 :   return err;
     182             : }
     183             : 
     184             : 
     185             : /* Print a warning if the server's version number is less than our
     186             :    version number.  Returns an error code on a connection problem.  */
     187             : static gpg_error_t
     188         539 : warn_version_mismatch (assuan_context_t ctx, const char *servername, int mode)
     189             : {
     190             :   gpg_error_t err;
     191             :   char *serverversion;
     192         539 :   const char *myversion = strusage (13);
     193             : 
     194         539 :   err = get_assuan_server_version (ctx, mode, &serverversion);
     195         539 :   if (err)
     196           0 :     log_error (_("error getting version from '%s': %s\n"),
     197             :                servername, gpg_strerror (err));
     198         539 :   else if (compare_version_strings (serverversion, myversion) < 0)
     199             :     {
     200             :       char *warn;
     201             : 
     202           0 :       warn = xtryasprintf (_("server '%s' is older than us (%s < %s)"),
     203             :                            servername, serverversion, myversion);
     204           0 :       if (!warn)
     205           0 :         err = gpg_error_from_syserror ();
     206             :       else
     207             :         {
     208           0 :           log_info (_("WARNING: %s\n"), warn);
     209           0 :           write_status_strings (STATUS_WARNING, "server_version_mismatch 0",
     210             :                                 " ", warn, NULL);
     211           0 :           xfree (warn);
     212             :         }
     213             :     }
     214         539 :   xfree (serverversion);
     215         539 :   return err;
     216             : }
     217             : 
     218             : 
     219             : /* Try to connect to the agent via socket or fork it off and work by
     220             :    pipes.  Handle the server's initial greeting */
     221             : static int
     222        1757 : start_agent (ctrl_t ctrl, int for_card)
     223             : {
     224             :   int rc;
     225             : 
     226             :   (void)ctrl;  /* Not yet used.  */
     227             : 
     228             :   /* Fixme: We need a context for each thread or serialize the access
     229             :      to the agent. */
     230        1757 :   if (agent_ctx)
     231        1218 :     rc = 0;
     232             :   else
     233             :     {
     234        1078 :       rc = start_new_gpg_agent (&agent_ctx,
     235             :                                 GPG_ERR_SOURCE_DEFAULT,
     236             :                                 opt.agent_program,
     237         539 :                                 opt.lc_ctype, opt.lc_messages,
     238             :                                 opt.session_env,
     239         539 :                                 opt.autostart, opt.verbose, DBG_IPC,
     240             :                                 NULL, NULL);
     241         539 :       if (!opt.autostart && gpg_err_code (rc) == GPG_ERR_NO_AGENT)
     242           0 :         {
     243             :           static int shown;
     244             : 
     245           0 :           if (!shown)
     246             :             {
     247           0 :               shown = 1;
     248           0 :               log_info (_("no gpg-agent running in this session\n"));
     249             :             }
     250             :         }
     251         539 :       else if (!rc
     252         539 :                && !(rc = warn_version_mismatch (agent_ctx, GPG_AGENT_NAME, 0)))
     253             :         {
     254             :           /* Tell the agent that we support Pinentry notifications.
     255             :              No error checking so that it will work also with older
     256             :              agents.  */
     257         539 :           assuan_transact (agent_ctx, "OPTION allow-pinentry-notify",
     258             :                            NULL, NULL, NULL, NULL, NULL, NULL);
     259             :           /* Tell the agent about what version we are aware.  This is
     260             :              here used to indirectly enable GPG_ERR_FULLY_CANCELED.  */
     261         539 :           assuan_transact (agent_ctx, "OPTION agent-awareness=2.1.0",
     262             :                            NULL, NULL, NULL, NULL, NULL, NULL);
     263             :           /* Pass on the pinentry mode.  */
     264         539 :           if (opt.pinentry_mode)
     265             :             {
     266           0 :               char *tmp = xasprintf ("OPTION pinentry-mode=%s",
     267           0 :                                      str_pinentry_mode (opt.pinentry_mode));
     268           0 :               rc = assuan_transact (agent_ctx, tmp,
     269             :                                NULL, NULL, NULL, NULL, NULL, NULL);
     270           0 :               xfree (tmp);
     271           0 :               if (rc)
     272             :                 {
     273           0 :                   log_error ("setting pinentry mode '%s' failed: %s\n",
     274           0 :                              str_pinentry_mode (opt.pinentry_mode),
     275             :                              gpg_strerror (rc));
     276           0 :                   write_status_error ("set_pinentry_mode", rc);
     277             :                 }
     278             :             }
     279             :         }
     280             :     }
     281             : 
     282        1757 :   if (!rc && for_card && !did_early_card_test)
     283             :     {
     284             :       /* Request the serial number of the card for an early test.  */
     285             :       struct agent_card_info_s info;
     286             : 
     287           0 :       memset (&info, 0, sizeof info);
     288             : 
     289           0 :       rc = warn_version_mismatch (agent_ctx, SCDAEMON_NAME, 2);
     290           0 :       if (!rc)
     291           0 :         rc = assuan_transact (agent_ctx, "SCD SERIALNO openpgp",
     292             :                               NULL, NULL, NULL, NULL,
     293             :                               learn_status_cb, &info);
     294           0 :       if (rc)
     295             :         {
     296           0 :           switch (gpg_err_code (rc))
     297             :             {
     298             :             case GPG_ERR_NOT_SUPPORTED:
     299             :             case GPG_ERR_NO_SCDAEMON:
     300           0 :               write_status_text (STATUS_CARDCTRL, "6");
     301           0 :               break;
     302             :             case GPG_ERR_OBJ_TERM_STATE:
     303           0 :               write_status_text (STATUS_CARDCTRL, "7");
     304           0 :               break;
     305             :             default:
     306           0 :               write_status_text (STATUS_CARDCTRL, "4");
     307           0 :               log_info ("selecting openpgp failed: %s\n", gpg_strerror (rc));
     308           0 :               break;
     309             :             }
     310             :         }
     311             : 
     312           0 :       if (!rc && is_status_enabled () && info.serialno)
     313             :         {
     314             :           char *buf;
     315             : 
     316           0 :           buf = xasprintf ("3 %s", info.serialno);
     317           0 :           write_status_text (STATUS_CARDCTRL, buf);
     318           0 :           xfree (buf);
     319             :         }
     320             : 
     321           0 :       agent_release_card_info (&info);
     322             : 
     323           0 :       if (!rc)
     324           0 :         did_early_card_test = 1;
     325             :     }
     326             : 
     327             : 
     328        1757 :   return rc;
     329             : }
     330             : 
     331             : 
     332             : /* Return a new malloced string by unescaping the string S.  Escaping
     333             :    is percent escaping and '+'/space mapping.  A binary nul will
     334             :    silently be replaced by a 0xFF.  Function returns NULL to indicate
     335             :    an out of memory status. */
     336             : static char *
     337           0 : unescape_status_string (const unsigned char *s)
     338             : {
     339           0 :   return percent_plus_unescape (s, 0xff);
     340             : }
     341             : 
     342             : 
     343             : /* Take a 20 byte hexencoded string and put it into the the provided
     344             :    20 byte buffer FPR in binary format. */
     345             : static int
     346           0 : unhexify_fpr (const char *hexstr, unsigned char *fpr)
     347             : {
     348             :   const char *s;
     349             :   int n;
     350             : 
     351           0 :   for (s=hexstr, n=0; hexdigitp (s); s++, n++)
     352             :     ;
     353           0 :   if (*s || (n != 40))
     354           0 :     return 0; /* no fingerprint (invalid or wrong length). */
     355           0 :   for (s=hexstr, n=0; *s; s += 2, n++)
     356           0 :     fpr[n] = xtoi_2 (s);
     357           0 :   return 1; /* okay */
     358             : }
     359             : 
     360             : /* Take the serial number from LINE and return it verbatim in a newly
     361             :    allocated string.  We make sure that only hex characters are
     362             :    returned. */
     363             : static char *
     364           0 : store_serialno (const char *line)
     365             : {
     366             :   const char *s;
     367             :   char *p;
     368             : 
     369           0 :   for (s=line; hexdigitp (s); s++)
     370             :     ;
     371           0 :   p = xtrymalloc (s + 1 - line);
     372           0 :   if (p)
     373             :     {
     374           0 :       memcpy (p, line, s-line);
     375           0 :       p[s-line] = 0;
     376             :     }
     377           0 :   return p;
     378             : }
     379             : 
     380             : 
     381             : 
     382             : /* This is a dummy data line callback.  */
     383             : static gpg_error_t
     384           0 : dummy_data_cb (void *opaque, const void *buffer, size_t length)
     385             : {
     386             :   (void)opaque;
     387             :   (void)buffer;
     388             :   (void)length;
     389           0 :   return 0;
     390             : }
     391             : 
     392             : /* A simple callback used to return the serialnumber of a card.  */
     393             : static gpg_error_t
     394           0 : get_serialno_cb (void *opaque, const char *line)
     395             : {
     396           0 :   char **serialno = opaque;
     397           0 :   const char *keyword = line;
     398             :   const char *s;
     399             :   int keywordlen, n;
     400             : 
     401           0 :   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
     402             :     ;
     403           0 :   while (spacep (line))
     404           0 :     line++;
     405             : 
     406           0 :   if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
     407             :     {
     408           0 :       if (*serialno)
     409           0 :         return gpg_error (GPG_ERR_CONFLICT); /* Unexpected status line. */
     410           0 :       for (n=0,s=line; hexdigitp (s); s++, n++)
     411             :         ;
     412           0 :       if (!n || (n&1)|| !(spacep (s) || !*s) )
     413           0 :         return gpg_error (GPG_ERR_ASS_PARAMETER);
     414           0 :       *serialno = xtrymalloc (n+1);
     415           0 :       if (!*serialno)
     416           0 :         return out_of_core ();
     417           0 :       memcpy (*serialno, line, n);
     418           0 :       (*serialno)[n] = 0;
     419             :     }
     420             : 
     421           0 :   return 0;
     422             : }
     423             : 
     424             : 
     425             : 
     426             : /* Release the card info structure INFO. */
     427             : void
     428           0 : agent_release_card_info (struct agent_card_info_s *info)
     429             : {
     430             :   int i;
     431             : 
     432           0 :   if (!info)
     433           0 :     return;
     434             : 
     435           0 :   xfree (info->reader); info->reader = NULL;
     436           0 :   xfree (info->serialno); info->serialno = NULL;
     437           0 :   xfree (info->apptype); info->apptype = NULL;
     438           0 :   xfree (info->disp_name); info->disp_name = NULL;
     439           0 :   xfree (info->disp_lang); info->disp_lang = NULL;
     440           0 :   xfree (info->pubkey_url); info->pubkey_url = NULL;
     441           0 :   xfree (info->login_data); info->login_data = NULL;
     442           0 :   info->cafpr1valid = info->cafpr2valid = info->cafpr3valid = 0;
     443           0 :   info->fpr1valid = info->fpr2valid = info->fpr3valid = 0;
     444           0 :   for (i=0; i < DIM(info->private_do); i++)
     445             :     {
     446           0 :       xfree (info->private_do[i]);
     447           0 :       info->private_do[i] = NULL;
     448             :     }
     449             : }
     450             : 
     451             : 
     452             : static gpg_error_t
     453           0 : learn_status_cb (void *opaque, const char *line)
     454             : {
     455           0 :   struct agent_card_info_s *parm = opaque;
     456           0 :   const char *keyword = line;
     457             :   int keywordlen;
     458             :   int i;
     459             : 
     460           0 :   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
     461             :     ;
     462           0 :   while (spacep (line))
     463           0 :     line++;
     464             : 
     465           0 :   if (keywordlen == 6 && !memcmp (keyword, "READER", keywordlen))
     466             :     {
     467           0 :       xfree (parm->reader);
     468           0 :       parm->reader = unescape_status_string (line);
     469             :     }
     470           0 :   else if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
     471             :     {
     472           0 :       xfree (parm->serialno);
     473           0 :       parm->serialno = store_serialno (line);
     474           0 :       parm->is_v2 = (strlen (parm->serialno) >= 16
     475           0 :                      && xtoi_2 (parm->serialno+12) >= 2 );
     476             :     }
     477           0 :   else if (keywordlen == 7 && !memcmp (keyword, "APPTYPE", keywordlen))
     478             :     {
     479           0 :       xfree (parm->apptype);
     480           0 :       parm->apptype = unescape_status_string (line);
     481             :     }
     482           0 :   else if (keywordlen == 9 && !memcmp (keyword, "DISP-NAME", keywordlen))
     483             :     {
     484           0 :       xfree (parm->disp_name);
     485           0 :       parm->disp_name = unescape_status_string (line);
     486             :     }
     487           0 :   else if (keywordlen == 9 && !memcmp (keyword, "DISP-LANG", keywordlen))
     488             :     {
     489           0 :       xfree (parm->disp_lang);
     490           0 :       parm->disp_lang = unescape_status_string (line);
     491             :     }
     492           0 :   else if (keywordlen == 8 && !memcmp (keyword, "DISP-SEX", keywordlen))
     493             :     {
     494           0 :       parm->disp_sex = *line == '1'? 1 : *line == '2' ? 2: 0;
     495             :     }
     496           0 :   else if (keywordlen == 10 && !memcmp (keyword, "PUBKEY-URL", keywordlen))
     497             :     {
     498           0 :       xfree (parm->pubkey_url);
     499           0 :       parm->pubkey_url = unescape_status_string (line);
     500             :     }
     501           0 :   else if (keywordlen == 10 && !memcmp (keyword, "LOGIN-DATA", keywordlen))
     502             :     {
     503           0 :       xfree (parm->login_data);
     504           0 :       parm->login_data = unescape_status_string (line);
     505             :     }
     506           0 :   else if (keywordlen == 11 && !memcmp (keyword, "SIG-COUNTER", keywordlen))
     507             :     {
     508           0 :       parm->sig_counter = strtoul (line, NULL, 0);
     509             :     }
     510           0 :   else if (keywordlen == 10 && !memcmp (keyword, "CHV-STATUS", keywordlen))
     511           0 :     {
     512             :       char *p, *buf;
     513             : 
     514           0 :       buf = p = unescape_status_string (line);
     515           0 :       if (buf)
     516             :         {
     517           0 :           while (spacep (p))
     518           0 :             p++;
     519           0 :           parm->chv1_cached = atoi (p);
     520           0 :           while (*p && !spacep (p))
     521           0 :             p++;
     522           0 :           while (spacep (p))
     523           0 :             p++;
     524           0 :           for (i=0; *p && i < 3; i++)
     525             :             {
     526           0 :               parm->chvmaxlen[i] = atoi (p);
     527           0 :               while (*p && !spacep (p))
     528           0 :                 p++;
     529           0 :               while (spacep (p))
     530           0 :                 p++;
     531             :             }
     532           0 :           for (i=0; *p && i < 3; i++)
     533             :             {
     534           0 :               parm->chvretry[i] = atoi (p);
     535           0 :               while (*p && !spacep (p))
     536           0 :                 p++;
     537           0 :               while (spacep (p))
     538           0 :                 p++;
     539             :             }
     540           0 :           xfree (buf);
     541             :         }
     542             :     }
     543           0 :   else if (keywordlen == 6 && !memcmp (keyword, "EXTCAP", keywordlen))
     544           0 :     {
     545             :       char *p, *p2, *buf;
     546             :       int abool;
     547             : 
     548           0 :       buf = p = unescape_status_string (line);
     549           0 :       if (buf)
     550             :         {
     551           0 :           for (p = strtok (buf, " "); p; p = strtok (NULL, " "))
     552             :             {
     553           0 :               p2 = strchr (p, '=');
     554           0 :               if (p2)
     555             :                 {
     556           0 :                   *p2++ = 0;
     557           0 :                   abool = (*p2 == '1');
     558           0 :                   if (!strcmp (p, "ki"))
     559           0 :                     parm->extcap.ki = abool;
     560           0 :                   else if (!strcmp (p, "aac"))
     561           0 :                     parm->extcap.aac = abool;
     562           0 :                   else if (!strcmp (p, "si"))
     563           0 :                     parm->status_indicator = strtoul (p2, NULL, 10);
     564             :                 }
     565             :             }
     566           0 :           xfree (buf);
     567             :         }
     568             :     }
     569           0 :   else if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
     570           0 :     {
     571           0 :       int no = atoi (line);
     572           0 :       while (*line && !spacep (line))
     573           0 :         line++;
     574           0 :       while (spacep (line))
     575           0 :         line++;
     576           0 :       if (no == 1)
     577           0 :         parm->fpr1valid = unhexify_fpr (line, parm->fpr1);
     578           0 :       else if (no == 2)
     579           0 :         parm->fpr2valid = unhexify_fpr (line, parm->fpr2);
     580           0 :       else if (no == 3)
     581           0 :         parm->fpr3valid = unhexify_fpr (line, parm->fpr3);
     582             :     }
     583           0 :   else if (keywordlen == 8 && !memcmp (keyword, "KEY-TIME", keywordlen))
     584           0 :     {
     585           0 :       int no = atoi (line);
     586           0 :       while (* line && !spacep (line))
     587           0 :         line++;
     588           0 :       while (spacep (line))
     589           0 :         line++;
     590           0 :       if (no == 1)
     591           0 :         parm->fpr1time = strtoul (line, NULL, 10);
     592           0 :       else if (no == 2)
     593           0 :         parm->fpr2time = strtoul (line, NULL, 10);
     594           0 :       else if (no == 3)
     595           0 :         parm->fpr3time = strtoul (line, NULL, 10);
     596             :     }
     597           0 :   else if (keywordlen == 6 && !memcmp (keyword, "CA-FPR", keywordlen))
     598           0 :     {
     599           0 :       int no = atoi (line);
     600           0 :       while (*line && !spacep (line))
     601           0 :         line++;
     602           0 :       while (spacep (line))
     603           0 :         line++;
     604           0 :       if (no == 1)
     605           0 :         parm->cafpr1valid = unhexify_fpr (line, parm->cafpr1);
     606           0 :       else if (no == 2)
     607           0 :         parm->cafpr2valid = unhexify_fpr (line, parm->cafpr2);
     608           0 :       else if (no == 3)
     609           0 :         parm->cafpr3valid = unhexify_fpr (line, parm->cafpr3);
     610             :     }
     611           0 :   else if (keywordlen == 8 && !memcmp (keyword, "KEY-ATTR", keywordlen))
     612           0 :     {
     613           0 :       int keyno = 0;
     614           0 :       int algo = PUBKEY_ALGO_RSA;
     615           0 :       int n = 0;
     616             : 
     617           0 :       sscanf (line, "%d %d %n", &keyno, &algo, &n);
     618           0 :       keyno--;
     619           0 :       if (keyno < 0 || keyno >= DIM (parm->key_attr))
     620           0 :         return 0;
     621             : 
     622           0 :       parm->key_attr[keyno].algo = algo;
     623           0 :       if (algo == PUBKEY_ALGO_RSA)
     624           0 :         parm->key_attr[keyno].nbits = strtoul (line+n+3, NULL, 10);
     625           0 :       else if (algo == PUBKEY_ALGO_ECDH || algo == PUBKEY_ALGO_ECDSA
     626           0 :                || algo == PUBKEY_ALGO_EDDSA)
     627           0 :         parm->key_attr[keyno].curve = openpgp_is_curve_supported (line+n, NULL);
     628             :     }
     629           0 :   else if (keywordlen == 12 && !memcmp (keyword, "PRIVATE-DO-", 11)
     630           0 :            && strchr("1234", keyword[11]))
     631             :     {
     632           0 :       int no = keyword[11] - '1';
     633           0 :       log_assert (no >= 0 && no <= 3);
     634           0 :       xfree (parm->private_do[no]);
     635           0 :       parm->private_do[no] = unescape_status_string (line);
     636             :     }
     637             : 
     638           0 :   return 0;
     639             : }
     640             : 
     641             : /* Call the scdaemon to learn about a smartcard */
     642             : int
     643           0 : agent_scd_learn (struct agent_card_info_s *info, int force)
     644             : {
     645             :   int rc;
     646             :   struct default_inq_parm_s parm;
     647             :   struct agent_card_info_s dummyinfo;
     648             : 
     649           0 :   if (!info)
     650           0 :     info = &dummyinfo;
     651           0 :   memset (info, 0, sizeof *info);
     652           0 :   memset (&parm, 0, sizeof parm);
     653             : 
     654           0 :   rc = start_agent (NULL, 1);
     655           0 :   if (rc)
     656           0 :     return rc;
     657             : 
     658             :   /* Send the serialno command to initialize the connection.  We don't
     659             :      care about the data returned.  If the card has already been
     660             :      initialized, this is a very fast command.  The main reason we
     661             :      need to do this here is to handle a card removed case so that an
     662             :      "l" command in --card-edit can be used to show ta newly inserted
     663             :      card.  We request the openpgp card because that is what we
     664             :      expect. */
     665           0 :   rc = assuan_transact (agent_ctx, "SCD SERIALNO openpgp",
     666             :                         NULL, NULL, NULL, NULL, NULL, NULL);
     667           0 :   if (rc)
     668           0 :     return rc;
     669             : 
     670           0 :   parm.ctx = agent_ctx;
     671           0 :   rc = assuan_transact (agent_ctx,
     672             :                         force ? "LEARN --sendinfo --force" : "LEARN --sendinfo",
     673             :                         dummy_data_cb, NULL, default_inq_cb, &parm,
     674             :                         learn_status_cb, info);
     675             :   /* Also try to get the key attributes.  */
     676           0 :   if (!rc)
     677           0 :     agent_scd_getattr ("KEY-ATTR", info);
     678             : 
     679           0 :   if (info == &dummyinfo)
     680           0 :     agent_release_card_info (info);
     681             : 
     682           0 :   return rc;
     683             : }
     684             : 
     685             : 
     686             : /* Send an APDU to the current card.  On success the status word is
     687             :    stored at R_SW.  With HEXAPDU being NULL only a RESET command is
     688             :    send to scd.  With HEXAPDU being the string "undefined" the command
     689             :    "SERIALNO undefined" is send to scd. */
     690             : gpg_error_t
     691           0 : agent_scd_apdu (const char *hexapdu, unsigned int *r_sw)
     692             : {
     693             :   gpg_error_t err;
     694             : 
     695             :   /* Start the agent but not with the card flag so that we do not
     696             :      autoselect the openpgp application.  */
     697           0 :   err = start_agent (NULL, 0);
     698           0 :   if (err)
     699           0 :     return err;
     700             : 
     701           0 :   if (!hexapdu)
     702             :     {
     703           0 :       err = assuan_transact (agent_ctx, "SCD RESET",
     704             :                              NULL, NULL, NULL, NULL, NULL, NULL);
     705             : 
     706             :     }
     707           0 :   else if (!strcmp (hexapdu, "undefined"))
     708             :     {
     709           0 :       err = assuan_transact (agent_ctx, "SCD SERIALNO undefined",
     710             :                              NULL, NULL, NULL, NULL, NULL, NULL);
     711             :     }
     712             :   else
     713             :     {
     714             :       char line[ASSUAN_LINELENGTH];
     715             :       membuf_t mb;
     716             :       unsigned char *data;
     717             :       size_t datalen;
     718             : 
     719           0 :       init_membuf (&mb, 256);
     720             : 
     721           0 :       snprintf (line, DIM(line), "SCD APDU %s", hexapdu);
     722           0 :       err = assuan_transact (agent_ctx, line,
     723             :                              put_membuf_cb, &mb, NULL, NULL, NULL, NULL);
     724           0 :       if (!err)
     725             :         {
     726           0 :           data = get_membuf (&mb, &datalen);
     727           0 :           if (!data)
     728           0 :             err = gpg_error_from_syserror ();
     729           0 :           else if (datalen < 2) /* Ooops */
     730           0 :             err = gpg_error (GPG_ERR_CARD);
     731             :           else
     732             :             {
     733           0 :               *r_sw = buf16_to_uint (data+datalen-2);
     734             :             }
     735           0 :           xfree (data);
     736             :         }
     737             :     }
     738             : 
     739           0 :   return err;
     740             : }
     741             : 
     742             : 
     743             : int
     744           0 : agent_keytocard (const char *hexgrip, int keyno, int force,
     745             :                  const char *serialno, const char *timestamp)
     746             : {
     747             :   int rc;
     748             :   char line[ASSUAN_LINELENGTH];
     749             :   struct default_inq_parm_s parm;
     750             : 
     751           0 :   memset (&parm, 0, sizeof parm);
     752             : 
     753           0 :   snprintf (line, DIM(line), "KEYTOCARD %s%s %s OPENPGP.%d %s",
     754             :             force?"--force ": "", hexgrip, serialno, keyno, timestamp);
     755             : 
     756           0 :   rc = start_agent (NULL, 1);
     757           0 :   if (rc)
     758           0 :     return rc;
     759           0 :   parm.ctx = agent_ctx;
     760             : 
     761           0 :   rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb, &parm,
     762             :                         NULL, NULL);
     763           0 :   if (rc)
     764           0 :     return rc;
     765             : 
     766           0 :   return rc;
     767             : }
     768             : 
     769             : /* Call the agent to retrieve a data object.  This function returns
     770             :    the data in the same structure as used by the learn command.  It is
     771             :    allowed to update such a structure using this commmand. */
     772             : int
     773           0 : agent_scd_getattr (const char *name, struct agent_card_info_s *info)
     774             : {
     775             :   int rc;
     776             :   char line[ASSUAN_LINELENGTH];
     777             :   struct default_inq_parm_s parm;
     778             : 
     779           0 :   memset (&parm, 0, sizeof parm);
     780             : 
     781           0 :   if (!*name)
     782           0 :     return gpg_error (GPG_ERR_INV_VALUE);
     783             : 
     784             :   /* We assume that NAME does not need escaping. */
     785           0 :   if (12 + strlen (name) > DIM(line)-1)
     786           0 :     return gpg_error (GPG_ERR_TOO_LARGE);
     787           0 :   stpcpy (stpcpy (line, "SCD GETATTR "), name);
     788             : 
     789           0 :   rc = start_agent (NULL, 1);
     790           0 :   if (rc)
     791           0 :     return rc;
     792             : 
     793           0 :   parm.ctx = agent_ctx;
     794           0 :   rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb, &parm,
     795             :                         learn_status_cb, info);
     796             : 
     797           0 :   return rc;
     798             : }
     799             : 
     800             : 
     801             : /* Send an setattr command to the SCdaemon.  SERIALNO is not actually
     802             :    used here but required by gpg 1.4's implementation of this code in
     803             :    cardglue.c. */
     804             : int
     805           0 : agent_scd_setattr (const char *name,
     806             :                    const unsigned char *value, size_t valuelen,
     807             :                    const char *serialno)
     808             : {
     809             :   int rc;
     810             :   char line[ASSUAN_LINELENGTH];
     811             :   char *p;
     812             :   struct default_inq_parm_s parm;
     813             : 
     814           0 :   memset (&parm, 0, sizeof parm);
     815             : 
     816             :   (void)serialno;
     817             : 
     818           0 :   if (!*name || !valuelen)
     819           0 :     return gpg_error (GPG_ERR_INV_VALUE);
     820             : 
     821             :   /* We assume that NAME does not need escaping. */
     822           0 :   if (12 + strlen (name) > DIM(line)-1)
     823           0 :     return gpg_error (GPG_ERR_TOO_LARGE);
     824             : 
     825           0 :   p = stpcpy (stpcpy (line, "SCD SETATTR "), name);
     826           0 :   *p++ = ' ';
     827           0 :   for (; valuelen; value++, valuelen--)
     828             :     {
     829           0 :       if (p >= line + DIM(line)-5 )
     830           0 :         return gpg_error (GPG_ERR_TOO_LARGE);
     831           0 :       if (*value < ' ' || *value == '+' || *value == '%')
     832             :         {
     833           0 :           sprintf (p, "%%%02X", *value);
     834           0 :           p += 3;
     835             :         }
     836           0 :       else if (*value == ' ')
     837           0 :         *p++ = '+';
     838             :       else
     839           0 :         *p++ = *value;
     840             :     }
     841           0 :   *p = 0;
     842             : 
     843           0 :   rc = start_agent (NULL, 1);
     844           0 :   if (!rc)
     845             :     {
     846           0 :       parm.ctx = agent_ctx;
     847           0 :       rc = assuan_transact (agent_ctx, line, NULL, NULL,
     848             :                             default_inq_cb, &parm, NULL, NULL);
     849             :     }
     850             : 
     851           0 :   status_sc_op_failure (rc);
     852           0 :   return rc;
     853             : }
     854             : 
     855             : 
     856             : 
     857             : /* Handle a CERTDATA inquiry.  Note, we only send the data,
     858             :    assuan_transact takes care of flushing and writing the END
     859             :    command. */
     860             : static gpg_error_t
     861           0 : inq_writecert_parms (void *opaque, const char *line)
     862             : {
     863             :   int rc;
     864           0 :   struct writecert_parm_s *parm = opaque;
     865             : 
     866           0 :   if (has_leading_keyword (line, "CERTDATA"))
     867             :     {
     868           0 :       rc = assuan_send_data (parm->dflt->ctx,
     869           0 :                              parm->certdata, parm->certdatalen);
     870             :     }
     871             :   else
     872           0 :     rc = default_inq_cb (parm->dflt, line);
     873             : 
     874           0 :   return rc;
     875             : }
     876             : 
     877             : 
     878             : /* Send a WRITECERT command to the SCdaemon. */
     879             : int
     880           0 : agent_scd_writecert (const char *certidstr,
     881             :                      const unsigned char *certdata, size_t certdatalen)
     882             : {
     883             :   int rc;
     884             :   char line[ASSUAN_LINELENGTH];
     885             :   struct writecert_parm_s parms;
     886             :   struct default_inq_parm_s dfltparm;
     887             : 
     888           0 :   memset (&dfltparm, 0, sizeof dfltparm);
     889             : 
     890           0 :   rc = start_agent (NULL, 1);
     891           0 :   if (rc)
     892           0 :     return rc;
     893             : 
     894           0 :   memset (&parms, 0, sizeof parms);
     895             : 
     896           0 :   snprintf (line, DIM(line), "SCD WRITECERT %s", certidstr);
     897           0 :   dfltparm.ctx = agent_ctx;
     898           0 :   parms.dflt = &dfltparm;
     899           0 :   parms.certdata = certdata;
     900           0 :   parms.certdatalen = certdatalen;
     901             : 
     902           0 :   rc = assuan_transact (agent_ctx, line, NULL, NULL,
     903             :                         inq_writecert_parms, &parms, NULL, NULL);
     904             : 
     905           0 :   return rc;
     906             : }
     907             : 
     908             : 
     909             : 
     910             : /* Handle a KEYDATA inquiry.  Note, we only send the data,
     911             :    assuan_transact takes care of flushing and writing the end */
     912             : static gpg_error_t
     913           0 : inq_writekey_parms (void *opaque, const char *line)
     914             : {
     915             :   int rc;
     916           0 :   struct writekey_parm_s *parm = opaque;
     917             : 
     918           0 :   if (has_leading_keyword (line, "KEYDATA"))
     919             :     {
     920           0 :       rc = assuan_send_data (parm->dflt->ctx, parm->keydata, parm->keydatalen);
     921             :     }
     922             :   else
     923           0 :     rc = default_inq_cb (parm->dflt, line);
     924             : 
     925           0 :   return rc;
     926             : }
     927             : 
     928             : 
     929             : /* Send a WRITEKEY command to the SCdaemon. */
     930             : int
     931           0 : agent_scd_writekey (int keyno, const char *serialno,
     932             :                     const unsigned char *keydata, size_t keydatalen)
     933             : {
     934             :   int rc;
     935             :   char line[ASSUAN_LINELENGTH];
     936             :   struct writekey_parm_s parms;
     937             :   struct default_inq_parm_s dfltparm;
     938             : 
     939           0 :   memset (&dfltparm, 0, sizeof dfltparm);
     940             : 
     941             :   (void)serialno;
     942             : 
     943           0 :   rc = start_agent (NULL, 1);
     944           0 :   if (rc)
     945           0 :     return rc;
     946             : 
     947           0 :   memset (&parms, 0, sizeof parms);
     948             : 
     949           0 :   snprintf (line, DIM(line), "SCD WRITEKEY --force OPENPGP.%d", keyno);
     950           0 :   dfltparm.ctx = agent_ctx;
     951           0 :   parms.dflt = &dfltparm;
     952           0 :   parms.keydata = keydata;
     953           0 :   parms.keydatalen = keydatalen;
     954             : 
     955           0 :   rc = assuan_transact (agent_ctx, line, NULL, NULL,
     956             :                         inq_writekey_parms, &parms, NULL, NULL);
     957             : 
     958           0 :   status_sc_op_failure (rc);
     959           0 :   return rc;
     960             : }
     961             : 
     962             : 
     963             : 
     964             : /* Status callback for the SCD GENKEY command. */
     965             : static gpg_error_t
     966           0 : scd_genkey_cb (void *opaque, const char *line)
     967             : {
     968           0 :   u32 *createtime = opaque;
     969           0 :   const char *keyword = line;
     970             :   int keywordlen;
     971             : 
     972           0 :   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
     973             :     ;
     974           0 :   while (spacep (line))
     975           0 :     line++;
     976             : 
     977           0 :  if (keywordlen == 14 && !memcmp (keyword,"KEY-CREATED-AT", keywordlen))
     978             :     {
     979           0 :       *createtime = (u32)strtoul (line, NULL, 10);
     980             :     }
     981           0 :   else if (keywordlen == 8 && !memcmp (keyword, "PROGRESS", keywordlen))
     982             :     {
     983           0 :       write_status_text (STATUS_PROGRESS, line);
     984             :     }
     985             : 
     986           0 :   return 0;
     987             : }
     988             : 
     989             : /* Send a GENKEY command to the SCdaemon.  If *CREATETIME is not 0,
     990             :   the value will be passed to SCDAEMON with --timestamp option so that
     991             :   the key is created with this.  Otherwise, timestamp was generated by
     992             :   SCDEAMON.  On success, creation time is stored back to
     993             :   CREATETIME.  */
     994             : int
     995           0 : agent_scd_genkey (int keyno, int force, u32 *createtime)
     996             : {
     997             :   int rc;
     998             :   char line[ASSUAN_LINELENGTH];
     999             :   gnupg_isotime_t tbuf;
    1000             :   struct default_inq_parm_s dfltparm;
    1001             : 
    1002           0 :   memset (&dfltparm, 0, sizeof dfltparm);
    1003             : 
    1004           0 :   rc = start_agent (NULL, 1);
    1005           0 :   if (rc)
    1006           0 :     return rc;
    1007             : 
    1008           0 :   if (*createtime)
    1009           0 :     epoch2isotime (tbuf, *createtime);
    1010             :   else
    1011           0 :     *tbuf = 0;
    1012             : 
    1013           0 :   snprintf (line, DIM(line), "SCD GENKEY %s%s %s %d",
    1014           0 :             *tbuf? "--timestamp=":"", tbuf,
    1015             :             force? "--force":"",
    1016             :             keyno);
    1017             : 
    1018           0 :   dfltparm.ctx = agent_ctx;
    1019           0 :   rc = assuan_transact (agent_ctx, line,
    1020             :                         NULL, NULL, default_inq_cb, &dfltparm,
    1021             :                         scd_genkey_cb, createtime);
    1022             : 
    1023           0 :   status_sc_op_failure (rc);
    1024           0 :   return rc;
    1025             : }
    1026             : 
    1027             : 
    1028             : 
    1029             : 
    1030             : /* Issue an SCD SERIALNO openpgp command and if SERIALNO is not NULL
    1031             :    ask the user to insert the requested card.  */
    1032             : gpg_error_t
    1033           0 : select_openpgp (const char *serialno)
    1034             : {
    1035             :   gpg_error_t err;
    1036             : 
    1037             :   /* Send the serialno command to initialize the connection.  Without
    1038             :      a given S/N we don't care about the data returned.  If the card
    1039             :      has already been initialized, this is a very fast command.  We
    1040             :      request the openpgp card because that is what we expect.
    1041             : 
    1042             :      Note that an opt.limit_card_insert_tries of 1 means: No tries at
    1043             :      all whereas 0 means do not limit the number of tries.  Due to the
    1044             :      sue of a pinentry prompt with a cancel option we use it here in a
    1045             :      boolean sense.  */
    1046           0 :   if (!serialno || opt.limit_card_insert_tries == 1)
    1047           0 :     err = assuan_transact (agent_ctx, "SCD SERIALNO openpgp",
    1048             :                            NULL, NULL, NULL, NULL, NULL, NULL);
    1049             :   else
    1050             :     {
    1051           0 :       char *this_sn = NULL;
    1052             :       char *desc;
    1053             :       int ask;
    1054             :       char *want_sn;
    1055             :       char *p;
    1056             : 
    1057           0 :       want_sn = xtrystrdup (serialno);
    1058           0 :       if (!want_sn)
    1059           0 :         return gpg_error_from_syserror ();
    1060           0 :       p = strchr (want_sn, '/');
    1061           0 :       if (p)
    1062           0 :         *p = 0;
    1063             : 
    1064             :       do
    1065             :         {
    1066           0 :           ask = 0;
    1067           0 :           err = assuan_transact (agent_ctx, "SCD SERIALNO openpgp",
    1068             :                                  NULL, NULL, NULL, NULL,
    1069             :                                  get_serialno_cb, &this_sn);
    1070           0 :           if (gpg_err_code (err) == GPG_ERR_CARD_NOT_PRESENT)
    1071           0 :             ask = 1;
    1072           0 :           else if (gpg_err_code (err) == GPG_ERR_NOT_SUPPORTED)
    1073           0 :             ask = 2;
    1074           0 :           else if (err)
    1075             :             ;
    1076           0 :           else if (this_sn)
    1077             :             {
    1078           0 :               if (strcmp (want_sn, this_sn))
    1079           0 :                 ask = 2;
    1080             :             }
    1081             : 
    1082           0 :           xfree (this_sn);
    1083           0 :           this_sn = NULL;
    1084             : 
    1085           0 :           if (ask)
    1086             :             {
    1087           0 :               char *formatted = NULL;
    1088           0 :               char *ocodeset = i18n_switchto_utf8 ();
    1089             : 
    1090           0 :               if (!strncmp (want_sn, "D27600012401", 12)
    1091           0 :                   && strlen (want_sn) == 32 )
    1092           0 :                 formatted = xtryasprintf ("(%.4s) %.8s",
    1093             :                                           want_sn + 16, want_sn + 20);
    1094             : 
    1095           0 :               err = 0;
    1096           0 :               desc = xtryasprintf
    1097             :                 ("%s:\n\n"
    1098             :                  "  \"%s\"",
    1099             :                  ask == 1
    1100             :                  ? _("Please insert the card with serial number")
    1101             :                  : _("Please remove the current card and "
    1102             :                      "insert the one with serial number"),
    1103             :                  formatted? formatted : want_sn);
    1104           0 :               if (!desc)
    1105           0 :                 err = gpg_error_from_syserror ();
    1106           0 :               xfree (formatted);
    1107           0 :               i18n_switchback (ocodeset);
    1108           0 :               if (!err)
    1109           0 :                 err = gpg_agent_get_confirmation (desc);
    1110           0 :               xfree (desc);
    1111             :             }
    1112             :         }
    1113           0 :       while (ask && !err);
    1114           0 :       xfree (want_sn);
    1115             :     }
    1116             : 
    1117           0 :   return err;
    1118             : }
    1119             : 
    1120             : 
    1121             : 
    1122             : /* Send a READCERT command to the SCdaemon. */
    1123             : int
    1124           0 : agent_scd_readcert (const char *certidstr,
    1125             :                     void **r_buf, size_t *r_buflen)
    1126             : {
    1127             :   int rc;
    1128             :   char line[ASSUAN_LINELENGTH];
    1129             :   membuf_t data;
    1130             :   size_t len;
    1131             :   struct default_inq_parm_s dfltparm;
    1132             : 
    1133           0 :   memset (&dfltparm, 0, sizeof dfltparm);
    1134             : 
    1135           0 :   *r_buf = NULL;
    1136           0 :   rc = start_agent (NULL, 1);
    1137           0 :   if (rc)
    1138           0 :     return rc;
    1139             : 
    1140           0 :   dfltparm.ctx = agent_ctx;
    1141             : 
    1142           0 :   init_membuf (&data, 2048);
    1143             : 
    1144           0 :   snprintf (line, DIM(line), "SCD READCERT %s", certidstr);
    1145           0 :   rc = assuan_transact (agent_ctx, line,
    1146             :                         put_membuf_cb, &data,
    1147             :                         default_inq_cb, &dfltparm,
    1148             :                         NULL, NULL);
    1149           0 :   if (rc)
    1150             :     {
    1151           0 :       xfree (get_membuf (&data, &len));
    1152           0 :       return rc;
    1153             :     }
    1154           0 :   *r_buf = get_membuf (&data, r_buflen);
    1155           0 :   if (!*r_buf)
    1156           0 :     return gpg_error (GPG_ERR_ENOMEM);
    1157             : 
    1158           0 :   return 0;
    1159             : }
    1160             : 
    1161             : 
    1162             : 
    1163             : /* Change the PIN of an OpenPGP card or reset the retry counter.
    1164             :    CHVNO 1: Change the PIN
    1165             :          2: For v1 cards: Same as 1.
    1166             :             For v2 cards: Reset the PIN using the Reset Code.
    1167             :          3: Change the admin PIN
    1168             :        101: Set a new PIN and reset the retry counter
    1169             :        102: For v1 cars: Same as 101.
    1170             :             For v2 cards: Set a new Reset Code.
    1171             :    SERIALNO is not used.
    1172             :  */
    1173             : int
    1174           0 : agent_scd_change_pin (int chvno, const char *serialno)
    1175             : {
    1176             :   int rc;
    1177             :   char line[ASSUAN_LINELENGTH];
    1178           0 :   const char *reset = "";
    1179             :   struct default_inq_parm_s dfltparm;
    1180             : 
    1181           0 :   memset (&dfltparm, 0, sizeof dfltparm);
    1182             : 
    1183             :   (void)serialno;
    1184             : 
    1185           0 :   if (chvno >= 100)
    1186           0 :     reset = "--reset";
    1187           0 :   chvno %= 100;
    1188             : 
    1189           0 :   rc = start_agent (NULL, 1);
    1190           0 :   if (rc)
    1191           0 :     return rc;
    1192           0 :   dfltparm.ctx = agent_ctx;
    1193             : 
    1194           0 :   snprintf (line, DIM(line), "SCD PASSWD %s %d", reset, chvno);
    1195           0 :   rc = assuan_transact (agent_ctx, line,
    1196             :                         NULL, NULL,
    1197             :                         default_inq_cb, &dfltparm,
    1198             :                         NULL, NULL);
    1199           0 :   status_sc_op_failure (rc);
    1200           0 :   return rc;
    1201             : }
    1202             : 
    1203             : 
    1204             : /* Perform a CHECKPIN operation.  SERIALNO should be the serial
    1205             :    number of the card - optionally followed by the fingerprint;
    1206             :    however the fingerprint is ignored here. */
    1207             : int
    1208           0 : agent_scd_checkpin  (const char *serialno)
    1209             : {
    1210             :   int rc;
    1211             :   char line[ASSUAN_LINELENGTH];
    1212             :   struct default_inq_parm_s dfltparm;
    1213             : 
    1214           0 :   memset (&dfltparm, 0, sizeof dfltparm);
    1215             : 
    1216           0 :   rc = start_agent (NULL, 1);
    1217           0 :   if (rc)
    1218           0 :     return rc;
    1219           0 :   dfltparm.ctx = agent_ctx;
    1220             : 
    1221           0 :   snprintf (line, DIM(line), "SCD CHECKPIN %s", serialno);
    1222           0 :   rc = assuan_transact (agent_ctx, line,
    1223             :                         NULL, NULL,
    1224             :                         default_inq_cb, &dfltparm,
    1225             :                         NULL, NULL);
    1226           0 :   status_sc_op_failure (rc);
    1227           0 :   return rc;
    1228             : }
    1229             : 
    1230             : 
    1231             : /* Dummy function, only used by the gpg 1.4 implementation. */
    1232             : void
    1233           0 : agent_clear_pin_cache (const char *sn)
    1234             : {
    1235             :   (void)sn;
    1236           0 : }
    1237             : 
    1238             : 
    1239             : 
    1240             : 
    1241             : /* Note: All strings shall be UTF-8. On success the caller needs to
    1242             :    free the string stored at R_PASSPHRASE. On error NULL will be
    1243             :    stored at R_PASSPHRASE and an appropriate fpf error code
    1244             :    returned. */
    1245             : gpg_error_t
    1246           0 : agent_get_passphrase (const char *cache_id,
    1247             :                       const char *err_msg,
    1248             :                       const char *prompt,
    1249             :                       const char *desc_msg,
    1250             :                       int repeat,
    1251             :                       int check,
    1252             :                       char **r_passphrase)
    1253             : {
    1254             :   int rc;
    1255             :   char line[ASSUAN_LINELENGTH];
    1256           0 :   char *arg1 = NULL;
    1257           0 :   char *arg2 = NULL;
    1258           0 :   char *arg3 = NULL;
    1259           0 :   char *arg4 = NULL;
    1260             :   membuf_t data;
    1261             :   struct default_inq_parm_s dfltparm;
    1262             : 
    1263           0 :   memset (&dfltparm, 0, sizeof dfltparm);
    1264             : 
    1265           0 :   *r_passphrase = NULL;
    1266             : 
    1267           0 :   rc = start_agent (NULL, 0);
    1268           0 :   if (rc)
    1269           0 :     return rc;
    1270           0 :   dfltparm.ctx = agent_ctx;
    1271             : 
    1272             :   /* Check that the gpg-agent understands the repeat option.  */
    1273           0 :   if (assuan_transact (agent_ctx,
    1274             :                        "GETINFO cmd_has_option GET_PASSPHRASE repeat",
    1275             :                        NULL, NULL, NULL, NULL, NULL, NULL))
    1276           0 :     return gpg_error (GPG_ERR_NOT_SUPPORTED);
    1277             : 
    1278           0 :   if (cache_id && *cache_id)
    1279           0 :     if (!(arg1 = percent_plus_escape (cache_id)))
    1280           0 :       goto no_mem;
    1281           0 :   if (err_msg && *err_msg)
    1282           0 :     if (!(arg2 = percent_plus_escape (err_msg)))
    1283           0 :       goto no_mem;
    1284           0 :   if (prompt && *prompt)
    1285           0 :     if (!(arg3 = percent_plus_escape (prompt)))
    1286           0 :       goto no_mem;
    1287           0 :   if (desc_msg && *desc_msg)
    1288           0 :     if (!(arg4 = percent_plus_escape (desc_msg)))
    1289           0 :       goto no_mem;
    1290             : 
    1291           0 :   snprintf (line, DIM(line),
    1292             :             "GET_PASSPHRASE --data --repeat=%d%s -- %s %s %s %s",
    1293             :             repeat,
    1294             :             check? " --check --qualitybar":"",
    1295             :             arg1? arg1:"X",
    1296             :             arg2? arg2:"X",
    1297             :             arg3? arg3:"X",
    1298             :             arg4? arg4:"X");
    1299           0 :   xfree (arg1);
    1300           0 :   xfree (arg2);
    1301           0 :   xfree (arg3);
    1302           0 :   xfree (arg4);
    1303             : 
    1304           0 :   init_membuf_secure (&data, 64);
    1305           0 :   rc = assuan_transact (agent_ctx, line,
    1306             :                         put_membuf_cb, &data,
    1307             :                         default_inq_cb, &dfltparm,
    1308             :                         NULL, NULL);
    1309             : 
    1310           0 :   if (rc)
    1311           0 :     xfree (get_membuf (&data, NULL));
    1312             :   else
    1313             :     {
    1314           0 :       put_membuf (&data, "", 1);
    1315           0 :       *r_passphrase = get_membuf (&data, NULL);
    1316           0 :       if (!*r_passphrase)
    1317           0 :         rc = gpg_error_from_syserror ();
    1318             :     }
    1319           0 :   return rc;
    1320             :  no_mem:
    1321           0 :   rc = gpg_error_from_syserror ();
    1322           0 :   xfree (arg1);
    1323           0 :   xfree (arg2);
    1324           0 :   xfree (arg3);
    1325           0 :   xfree (arg4);
    1326           0 :   return rc;
    1327             : }
    1328             : 
    1329             : 
    1330             : gpg_error_t
    1331           0 : agent_clear_passphrase (const char *cache_id)
    1332             : {
    1333             :   int rc;
    1334             :   char line[ASSUAN_LINELENGTH];
    1335             :   struct default_inq_parm_s dfltparm;
    1336             : 
    1337           0 :   memset (&dfltparm, 0, sizeof dfltparm);
    1338             : 
    1339           0 :   if (!cache_id || !*cache_id)
    1340           0 :     return 0;
    1341             : 
    1342           0 :   rc = start_agent (NULL, 0);
    1343           0 :   if (rc)
    1344           0 :     return rc;
    1345           0 :   dfltparm.ctx = agent_ctx;
    1346             : 
    1347           0 :   snprintf (line, DIM(line), "CLEAR_PASSPHRASE %s", cache_id);
    1348           0 :   return assuan_transact (agent_ctx, line,
    1349             :                           NULL, NULL,
    1350             :                           default_inq_cb, &dfltparm,
    1351             :                           NULL, NULL);
    1352             : }
    1353             : 
    1354             : 
    1355             : /* Ask the agent to pop up a confirmation dialog with the text DESC
    1356             :    and an okay and cancel button. */
    1357             : gpg_error_t
    1358           0 : gpg_agent_get_confirmation (const char *desc)
    1359             : {
    1360             :   int rc;
    1361             :   char *tmp;
    1362             :   char line[ASSUAN_LINELENGTH];
    1363             :   struct default_inq_parm_s dfltparm;
    1364             : 
    1365           0 :   memset (&dfltparm, 0, sizeof dfltparm);
    1366             : 
    1367           0 :   rc = start_agent (NULL, 0);
    1368           0 :   if (rc)
    1369           0 :     return rc;
    1370           0 :   dfltparm.ctx = agent_ctx;
    1371             : 
    1372           0 :   tmp = percent_plus_escape (desc);
    1373           0 :   if (!tmp)
    1374           0 :     return gpg_error_from_syserror ();
    1375           0 :   snprintf (line, DIM(line), "GET_CONFIRMATION %s", tmp);
    1376           0 :   xfree (tmp);
    1377             : 
    1378           0 :   rc = assuan_transact (agent_ctx, line,
    1379             :                         NULL, NULL,
    1380             :                         default_inq_cb, &dfltparm,
    1381             :                         NULL, NULL);
    1382           0 :   return rc;
    1383             : }
    1384             : 
    1385             : 
    1386             : /* Return the S2K iteration count as computed by gpg-agent.  */
    1387             : gpg_error_t
    1388           3 : agent_get_s2k_count (unsigned long *r_count)
    1389             : {
    1390             :   gpg_error_t err;
    1391             :   membuf_t data;
    1392             :   char *buf;
    1393             : 
    1394           3 :   *r_count = 0;
    1395             : 
    1396           3 :   err = start_agent (NULL, 0);
    1397           3 :   if (err)
    1398           0 :     return err;
    1399             : 
    1400           3 :   init_membuf (&data, 32);
    1401           3 :   err = assuan_transact (agent_ctx, "GETINFO s2k_count",
    1402             :                         put_membuf_cb, &data,
    1403             :                         NULL, NULL, NULL, NULL);
    1404           3 :   if (err)
    1405           0 :     xfree (get_membuf (&data, NULL));
    1406             :   else
    1407             :     {
    1408           3 :       put_membuf (&data, "", 1);
    1409           3 :       buf = get_membuf (&data, NULL);
    1410           3 :       if (!buf)
    1411           0 :         err = gpg_error_from_syserror ();
    1412             :       else
    1413             :         {
    1414           3 :           *r_count = strtoul (buf, NULL, 10);
    1415           3 :           xfree (buf);
    1416             :         }
    1417             :     }
    1418           3 :   return err;
    1419             : }
    1420             : 
    1421             : 
    1422             : 
    1423             : /* Ask the agent whether a secret key for the given public key is
    1424             :    available.  Returns 0 if available.  */
    1425             : gpg_error_t
    1426         790 : agent_probe_secret_key (ctrl_t ctrl, PKT_public_key *pk)
    1427             : {
    1428             :   gpg_error_t err;
    1429             :   char line[ASSUAN_LINELENGTH];
    1430             :   char *hexgrip;
    1431             : 
    1432         790 :   err = start_agent (ctrl, 0);
    1433         790 :   if (err)
    1434           0 :     return err;
    1435             : 
    1436         790 :   err = hexkeygrip_from_pk (pk, &hexgrip);
    1437         790 :   if (err)
    1438           0 :     return err;
    1439             : 
    1440         790 :   snprintf (line, sizeof line, "HAVEKEY %s", hexgrip);
    1441         790 :   xfree (hexgrip);
    1442             : 
    1443         790 :   err = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
    1444         790 :   return err;
    1445             : }
    1446             : 
    1447             : /* Ask the agent whether a secret key is available for any of the
    1448             :    keys (primary or sub) in KEYBLOCK.  Returns 0 if available.  */
    1449             : gpg_error_t
    1450         427 : agent_probe_any_secret_key (ctrl_t ctrl, kbnode_t keyblock)
    1451             : {
    1452             :   gpg_error_t err;
    1453             :   char line[ASSUAN_LINELENGTH];
    1454             :   char *p;
    1455             :   kbnode_t kbctx, node;
    1456             :   int nkeys;
    1457             :   unsigned char grip[20];
    1458             : 
    1459         427 :   err = start_agent (ctrl, 0);
    1460         427 :   if (err)
    1461           0 :     return err;
    1462             : 
    1463         427 :   err = gpg_error (GPG_ERR_NO_SECKEY); /* Just in case no key was
    1464             :                                           found in KEYBLOCK.  */
    1465         427 :   p = stpcpy (line, "HAVEKEY");
    1466        3411 :   for (kbctx=NULL, nkeys=0; (node = walk_kbnode (keyblock, &kbctx, 0)); )
    1467        2557 :     if (node->pkt->pkttype == PKT_PUBLIC_KEY
    1468        2130 :         || node->pkt->pkttype == PKT_PUBLIC_SUBKEY
    1469        1675 :         || node->pkt->pkttype == PKT_SECRET_KEY
    1470        1675 :         || node->pkt->pkttype == PKT_SECRET_SUBKEY)
    1471             :       {
    1472         882 :         if (nkeys && ((p - line) + 41) > (ASSUAN_LINELENGTH - 2))
    1473             :           {
    1474           0 :             err = assuan_transact (agent_ctx, line,
    1475             :                                    NULL, NULL, NULL, NULL, NULL, NULL);
    1476           0 :             if (err != gpg_err_code (GPG_ERR_NO_SECKEY))
    1477           0 :               break; /* Seckey available or unexpected error - ready.  */
    1478           0 :             p = stpcpy (line, "HAVEKEY");
    1479           0 :             nkeys = 0;
    1480             :           }
    1481             : 
    1482         882 :         err = keygrip_from_pk (node->pkt->pkt.public_key, grip);
    1483         882 :         if (err)
    1484           0 :           return err;
    1485         882 :         *p++ = ' ';
    1486         882 :         bin2hex (grip, 20, p);
    1487         882 :         p += 40;
    1488         882 :         nkeys++;
    1489             :       }
    1490             : 
    1491         427 :   if (!err && nkeys)
    1492         427 :     err = assuan_transact (agent_ctx, line,
    1493             :                            NULL, NULL, NULL, NULL, NULL, NULL);
    1494             : 
    1495         427 :   return err;
    1496             : }
    1497             : 
    1498             : 
    1499             : 
    1500             : struct keyinfo_data_parm_s
    1501             : {
    1502             :   char *serialno;
    1503             :   int cleartext;
    1504             : };
    1505             : 
    1506             : 
    1507             : static gpg_error_t
    1508          60 : keyinfo_status_cb (void *opaque, const char *line)
    1509             : {
    1510          60 :   struct keyinfo_data_parm_s *data = opaque;
    1511             :   int is_smartcard;
    1512             :   char *s;
    1513             : 
    1514          60 :   if ((s = has_leading_keyword (line, "KEYINFO")) && data)
    1515             :     {
    1516             :       /* Parse the arguments:
    1517             :        *      0        1        2        3       4          5
    1518             :        *   <keygrip> <type> <serialno> <idstr> <cached> <protection>
    1519             :        */
    1520             :       char *fields[6];
    1521             : 
    1522          60 :       if (split_fields (s, fields, DIM (fields)) == 6)
    1523             :         {
    1524          60 :           is_smartcard = (fields[1][0] == 'T');
    1525          60 :           if (is_smartcard && !data->serialno && strcmp (fields[2], "-"))
    1526           0 :             data->serialno = xtrystrdup (fields[2]);
    1527             :           /* 'P' for protected, 'C' for clear */
    1528          60 :           data->cleartext = (fields[5][0] == 'C');
    1529             :         }
    1530             :     }
    1531          60 :   return 0;
    1532             : }
    1533             : 
    1534             : 
    1535             : /* Return the serial number for a secret key.  If the returned serial
    1536             :    number is NULL, the key is not stored on a smartcard.  Caller needs
    1537             :    to free R_SERIALNO.
    1538             : 
    1539             :    if r_cleartext is not NULL, the referenced int will be set to 1 if
    1540             :    the agent's copy of the key is stored in the clear, or 0 otherwise
    1541             : */
    1542             : gpg_error_t
    1543          60 : agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip,
    1544             :                    char **r_serialno, int *r_cleartext)
    1545             : {
    1546             :   gpg_error_t err;
    1547             :   char line[ASSUAN_LINELENGTH];
    1548             :   struct keyinfo_data_parm_s keyinfo;
    1549             : 
    1550          60 :   memset (&keyinfo, 0,sizeof keyinfo);
    1551             : 
    1552          60 :   *r_serialno = NULL;
    1553             : 
    1554          60 :   err = start_agent (ctrl, 0);
    1555          60 :   if (err)
    1556           0 :     return err;
    1557             : 
    1558          60 :   if (!hexkeygrip || strlen (hexkeygrip) != 40)
    1559           0 :     return gpg_error (GPG_ERR_INV_VALUE);
    1560             : 
    1561          60 :   snprintf (line, DIM(line), "KEYINFO %s", hexkeygrip);
    1562             : 
    1563          60 :   err = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL,
    1564             :                          keyinfo_status_cb, &keyinfo);
    1565          60 :   if (!err && keyinfo.serialno)
    1566             :     {
    1567             :       /* Sanity check for bad characters.  */
    1568           0 :       if (strpbrk (keyinfo.serialno, ":\n\r"))
    1569           0 :         err = GPG_ERR_INV_VALUE;
    1570             :     }
    1571          60 :   if (err)
    1572           0 :     xfree (keyinfo.serialno);
    1573             :   else
    1574             :     {
    1575          60 :       *r_serialno = keyinfo.serialno;
    1576          60 :       if (r_cleartext)
    1577           5 :         *r_cleartext = keyinfo.cleartext;
    1578             :     }
    1579          60 :   return err;
    1580             : }
    1581             : 
    1582             : 
    1583             : /* Status callback for agent_import_key, agent_export_key and
    1584             :    agent_genkey.  */
    1585             : static gpg_error_t
    1586         458 : cache_nonce_status_cb (void *opaque, const char *line)
    1587             : {
    1588         458 :   struct cache_nonce_parm_s *parm = opaque;
    1589             :   const char *s;
    1590             : 
    1591         458 :   if ((s = has_leading_keyword (line, "CACHE_NONCE")))
    1592             :     {
    1593           4 :       if (parm->cache_nonce_addr)
    1594             :         {
    1595           4 :           xfree (*parm->cache_nonce_addr);
    1596           4 :           *parm->cache_nonce_addr = xtrystrdup (s);
    1597             :         }
    1598             :     }
    1599         454 :   else if ((s = has_leading_keyword (line, "PASSWD_NONCE")))
    1600             :     {
    1601           0 :       if (parm->passwd_nonce_addr)
    1602             :         {
    1603           0 :           xfree (*parm->passwd_nonce_addr);
    1604           0 :           *parm->passwd_nonce_addr = xtrystrdup (s);
    1605             :         }
    1606             :     }
    1607         454 :   else if ((s = has_leading_keyword (line, "PROGRESS")))
    1608             :     {
    1609         449 :       if (opt.enable_progress_filter)
    1610           0 :         write_status_text (STATUS_PROGRESS, s);
    1611             :     }
    1612             : 
    1613         458 :   return 0;
    1614             : }
    1615             : 
    1616             : 
    1617             : 
    1618             : /* Handle a KEYPARMS inquiry.  Note, we only send the data,
    1619             :    assuan_transact takes care of flushing and writing the end */
    1620             : static gpg_error_t
    1621           8 : inq_genkey_parms (void *opaque, const char *line)
    1622             : {
    1623           8 :   struct genkey_parm_s *parm = opaque;
    1624             :   gpg_error_t err;
    1625             : 
    1626           8 :   if (has_leading_keyword (line, "KEYPARAM"))
    1627             :     {
    1628          10 :       err = assuan_send_data (parm->dflt->ctx,
    1629           5 :                               parm->keyparms, strlen (parm->keyparms));
    1630             :     }
    1631           3 :   else if (has_leading_keyword (line, "NEWPASSWD") && parm->passphrase)
    1632             :     {
    1633           0 :       err = assuan_send_data (parm->dflt->ctx,
    1634           0 :                               parm->passphrase,  strlen (parm->passphrase));
    1635             :     }
    1636             :   else
    1637           3 :     err = default_inq_cb (parm->dflt, line);
    1638             : 
    1639           8 :   return err;
    1640             : }
    1641             : 
    1642             : 
    1643             : /* Call the agent to generate a new key.  KEYPARMS is the usual
    1644             :    S-expression giving the parameters of the key.  gpg-agent passes it
    1645             :    gcry_pk_genkey.  If NO_PROTECTION is true the agent is advised not
    1646             :    to protect the generated key.  If NO_PROTECTION is not set and
    1647             :    PASSPHRASE is not NULL the agent is requested to protect the key
    1648             :    with that passphrase instead of asking for one.  */
    1649             : gpg_error_t
    1650           5 : agent_genkey (ctrl_t ctrl, char **cache_nonce_addr, char **passwd_nonce_addr,
    1651             :               const char *keyparms, int no_protection,
    1652             :               const char *passphrase, gcry_sexp_t *r_pubkey)
    1653             : {
    1654             :   gpg_error_t err;
    1655             :   struct genkey_parm_s gk_parm;
    1656             :   struct cache_nonce_parm_s cn_parm;
    1657             :   struct default_inq_parm_s dfltparm;
    1658             :   membuf_t data;
    1659             :   size_t len;
    1660             :   unsigned char *buf;
    1661             :   char line[ASSUAN_LINELENGTH];
    1662             : 
    1663           5 :   memset (&dfltparm, 0, sizeof dfltparm);
    1664           5 :   dfltparm.ctrl = ctrl;
    1665             : 
    1666           5 :   *r_pubkey = NULL;
    1667           5 :   err = start_agent (ctrl, 0);
    1668           5 :   if (err)
    1669           0 :     return err;
    1670           5 :   dfltparm.ctx = agent_ctx;
    1671             : 
    1672           5 :   if (passwd_nonce_addr && *passwd_nonce_addr)
    1673             :     ; /* A RESET would flush the passwd nonce cache.  */
    1674             :   else
    1675             :     {
    1676           5 :       err = assuan_transact (agent_ctx, "RESET",
    1677             :                              NULL, NULL, NULL, NULL, NULL, NULL);
    1678           5 :       if (err)
    1679           0 :         return err;
    1680             :     }
    1681             : 
    1682           5 :   init_membuf (&data, 1024);
    1683           5 :   gk_parm.dflt     = &dfltparm;
    1684           5 :   gk_parm.keyparms = keyparms;
    1685           5 :   gk_parm.passphrase = passphrase;
    1686           9 :   snprintf (line, sizeof line, "GENKEY%s%s%s%s%s",
    1687             :             no_protection? " --no-protection" :
    1688           2 :             passphrase   ? " --inq-passwd" :
    1689             :             /*          */ "",
    1690           0 :             passwd_nonce_addr && *passwd_nonce_addr? " --passwd-nonce=":"",
    1691           0 :             passwd_nonce_addr && *passwd_nonce_addr? *passwd_nonce_addr:"",
    1692           5 :             cache_nonce_addr && *cache_nonce_addr? " ":"",
    1693           5 :             cache_nonce_addr && *cache_nonce_addr? *cache_nonce_addr:"");
    1694           5 :   cn_parm.cache_nonce_addr = cache_nonce_addr;
    1695           5 :   cn_parm.passwd_nonce_addr = NULL;
    1696           5 :   err = assuan_transact (agent_ctx, line,
    1697             :                          put_membuf_cb, &data,
    1698             :                          inq_genkey_parms, &gk_parm,
    1699             :                          cache_nonce_status_cb, &cn_parm);
    1700           5 :   if (err)
    1701             :     {
    1702           0 :       xfree (get_membuf (&data, &len));
    1703           0 :       return err;
    1704             :     }
    1705             : 
    1706           5 :   buf = get_membuf (&data, &len);
    1707           5 :   if (!buf)
    1708           0 :     err = gpg_error_from_syserror ();
    1709             :   else
    1710             :     {
    1711           5 :       err = gcry_sexp_sscan (r_pubkey, NULL, buf, len);
    1712           5 :       xfree (buf);
    1713             :     }
    1714           5 :   return err;
    1715             : }
    1716             : 
    1717             : 
    1718             : 
    1719             : /* Call the agent to read the public key part for a given keygrip.  If
    1720             :    FROMCARD is true, the key is directly read from the current
    1721             :    smartcard. In this case HEXKEYGRIP should be the keyID
    1722             :    (e.g. OPENPGP.3). */
    1723             : gpg_error_t
    1724           0 : agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip,
    1725             :                unsigned char **r_pubkey)
    1726             : {
    1727             :   gpg_error_t err;
    1728             :   membuf_t data;
    1729             :   size_t len;
    1730             :   unsigned char *buf;
    1731             :   char line[ASSUAN_LINELENGTH];
    1732             :   struct default_inq_parm_s dfltparm;
    1733             : 
    1734           0 :   memset (&dfltparm, 0, sizeof dfltparm);
    1735           0 :   dfltparm.ctrl = ctrl;
    1736             : 
    1737           0 :   *r_pubkey = NULL;
    1738           0 :   err = start_agent (ctrl, 0);
    1739           0 :   if (err)
    1740           0 :     return err;
    1741           0 :   dfltparm.ctx = agent_ctx;
    1742             : 
    1743           0 :   err = assuan_transact (agent_ctx, "RESET",NULL, NULL, NULL, NULL, NULL, NULL);
    1744           0 :   if (err)
    1745           0 :     return err;
    1746             : 
    1747           0 :   snprintf (line, DIM(line), "READKEY %s%s", fromcard? "--card ":"",
    1748             :             hexkeygrip);
    1749             : 
    1750           0 :   init_membuf (&data, 1024);
    1751           0 :   err = assuan_transact (agent_ctx, line,
    1752             :                          put_membuf_cb, &data,
    1753             :                          default_inq_cb, &dfltparm,
    1754             :                          NULL, NULL);
    1755           0 :   if (err)
    1756             :     {
    1757           0 :       xfree (get_membuf (&data, &len));
    1758           0 :       return err;
    1759             :     }
    1760           0 :   buf = get_membuf (&data, &len);
    1761           0 :   if (!buf)
    1762           0 :     return gpg_error_from_syserror ();
    1763           0 :   if (!gcry_sexp_canon_len (buf, len, NULL, NULL))
    1764             :     {
    1765           0 :       xfree (buf);
    1766           0 :       return gpg_error (GPG_ERR_INV_SEXP);
    1767             :     }
    1768           0 :   *r_pubkey = buf;
    1769           0 :   return 0;
    1770             : }
    1771             : 
    1772             : 
    1773             : 
    1774             : /* Call the agent to do a sign operation using the key identified by
    1775             :    the hex string KEYGRIP.  DESC is a description of the key to be
    1776             :    displayed if the agent needs to ask for the PIN.  DIGEST and
    1777             :    DIGESTLEN is the hash value to sign and DIGESTALGO the algorithm id
    1778             :    used to compute the digest.  If CACHE_NONCE is used the agent is
    1779             :    advised to first try a passphrase associated with that nonce. */
    1780             : gpg_error_t
    1781         141 : agent_pksign (ctrl_t ctrl, const char *cache_nonce,
    1782             :               const char *keygrip, const char *desc,
    1783             :               u32 *keyid, u32 *mainkeyid, int pubkey_algo,
    1784             :               unsigned char *digest, size_t digestlen, int digestalgo,
    1785             :               gcry_sexp_t *r_sigval)
    1786             : {
    1787             :   gpg_error_t err;
    1788             :   char line[ASSUAN_LINELENGTH];
    1789             :   membuf_t data;
    1790             :   struct default_inq_parm_s dfltparm;
    1791             : 
    1792         141 :   memset (&dfltparm, 0, sizeof dfltparm);
    1793         141 :   dfltparm.ctrl = ctrl;
    1794         141 :   dfltparm.keyinfo.keyid       = keyid;
    1795         141 :   dfltparm.keyinfo.mainkeyid   = mainkeyid;
    1796         141 :   dfltparm.keyinfo.pubkey_algo = pubkey_algo;
    1797             : 
    1798         141 :   *r_sigval = NULL;
    1799         141 :   err = start_agent (ctrl, 0);
    1800         141 :   if (err)
    1801           0 :     return err;
    1802         141 :   dfltparm.ctx = agent_ctx;
    1803             : 
    1804         141 :   if (digestlen*2 + 50 > DIM(line))
    1805           0 :     return gpg_error (GPG_ERR_GENERAL);
    1806             : 
    1807         141 :   err = assuan_transact (agent_ctx, "RESET",
    1808             :                          NULL, NULL, NULL, NULL, NULL, NULL);
    1809         141 :   if (err)
    1810           0 :     return err;
    1811             : 
    1812         141 :   snprintf (line, DIM(line), "SIGKEY %s", keygrip);
    1813         141 :   err = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
    1814         141 :   if (err)
    1815           0 :     return err;
    1816             : 
    1817         141 :   if (desc)
    1818             :     {
    1819         141 :       snprintf (line, DIM(line), "SETKEYDESC %s", desc);
    1820         141 :       err = assuan_transact (agent_ctx, line,
    1821             :                             NULL, NULL, NULL, NULL, NULL, NULL);
    1822         141 :       if (err)
    1823           0 :         return err;
    1824             :     }
    1825             : 
    1826         141 :   snprintf (line, sizeof line, "SETHASH %d ", digestalgo);
    1827         141 :   bin2hex (digest, digestlen, line + strlen (line));
    1828         141 :   err = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
    1829         141 :   if (err)
    1830           0 :     return err;
    1831             : 
    1832         141 :   init_membuf (&data, 1024);
    1833             : 
    1834         141 :   snprintf (line, sizeof line, "PKSIGN%s%s",
    1835             :             cache_nonce? " -- ":"",
    1836             :             cache_nonce? cache_nonce:"");
    1837         141 :   err = assuan_transact (agent_ctx, line,
    1838             :                          put_membuf_cb, &data,
    1839             :                          default_inq_cb, &dfltparm,
    1840             :                          NULL, NULL);
    1841         141 :   if (err)
    1842           0 :     xfree (get_membuf (&data, NULL));
    1843             :   else
    1844             :     {
    1845             :       unsigned char *buf;
    1846             :       size_t len;
    1847             : 
    1848         141 :       buf = get_membuf (&data, &len);
    1849         141 :       if (!buf)
    1850           0 :         err = gpg_error_from_syserror ();
    1851             :       else
    1852             :         {
    1853         141 :           err = gcry_sexp_sscan (r_sigval, NULL, buf, len);
    1854         141 :           xfree (buf);
    1855             :         }
    1856             :     }
    1857         141 :   return err;
    1858             : }
    1859             : 
    1860             : 
    1861             : 
    1862             : /* Handle a CIPHERTEXT inquiry.  Note, we only send the data,
    1863             :    assuan_transact takes care of flushing and writing the END. */
    1864             : static gpg_error_t
    1865         269 : inq_ciphertext_cb (void *opaque, const char *line)
    1866             : {
    1867         269 :   struct cipher_parm_s *parm = opaque;
    1868             :   int rc;
    1869             : 
    1870         269 :   if (has_leading_keyword (line, "CIPHERTEXT"))
    1871             :     {
    1872         269 :       assuan_begin_confidential (parm->ctx);
    1873         538 :       rc = assuan_send_data (parm->dflt->ctx,
    1874         269 :                              parm->ciphertext, parm->ciphertextlen);
    1875         269 :       assuan_end_confidential (parm->ctx);
    1876             :     }
    1877             :   else
    1878           0 :     rc = default_inq_cb (parm->dflt, line);
    1879             : 
    1880         269 :   return rc;
    1881             : }
    1882             : 
    1883             : 
    1884             : /* Check whether there is any padding info from the agent.  */
    1885             : static gpg_error_t
    1886         269 : padding_info_cb (void *opaque, const char *line)
    1887             : {
    1888         269 :   int *r_padding = opaque;
    1889             :   const char *s;
    1890             : 
    1891         269 :   if ((s=has_leading_keyword (line, "PADDING")))
    1892             :     {
    1893           0 :       *r_padding = atoi (s);
    1894             :     }
    1895             : 
    1896         269 :   return 0;
    1897             : }
    1898             : 
    1899             : 
    1900             : /* Call the agent to do a decrypt operation using the key identified
    1901             :    by the hex string KEYGRIP and the input data S_CIPHERTEXT.  On the
    1902             :    success the decoded value is stored verbatim at R_BUF and its
    1903             :    length at R_BUF; the callers needs to release it.  KEYID, MAINKEYID
    1904             :    and PUBKEY_ALGO are used to construct additional promots or status
    1905             :    messages.   The padding information is stored at R_PADDING with -1
    1906             :    for not known.  */
    1907             : gpg_error_t
    1908         269 : agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
    1909             :                  u32 *keyid, u32 *mainkeyid, int pubkey_algo,
    1910             :                  gcry_sexp_t s_ciphertext,
    1911             :                  unsigned char **r_buf, size_t *r_buflen, int *r_padding)
    1912             : {
    1913             :   gpg_error_t err;
    1914             :   char line[ASSUAN_LINELENGTH];
    1915             :   membuf_t data;
    1916             :   size_t n, len;
    1917             :   char *p, *buf, *endp;
    1918             :   struct default_inq_parm_s dfltparm;
    1919             : 
    1920         269 :   memset (&dfltparm, 0, sizeof dfltparm);
    1921         269 :   dfltparm.ctrl = ctrl;
    1922         269 :   dfltparm.keyinfo.keyid       = keyid;
    1923         269 :   dfltparm.keyinfo.mainkeyid   = mainkeyid;
    1924         269 :   dfltparm.keyinfo.pubkey_algo = pubkey_algo;
    1925             : 
    1926         269 :   if (!keygrip || strlen(keygrip) != 40
    1927         269 :       || !s_ciphertext || !r_buf || !r_buflen || !r_padding)
    1928           0 :     return gpg_error (GPG_ERR_INV_VALUE);
    1929             : 
    1930         269 :   *r_buf = NULL;
    1931         269 :   *r_padding = -1;
    1932             : 
    1933         269 :   err = start_agent (ctrl, 0);
    1934         269 :   if (err)
    1935           0 :     return err;
    1936         269 :   dfltparm.ctx = agent_ctx;
    1937             : 
    1938         269 :   err = assuan_transact (agent_ctx, "RESET",
    1939             :                          NULL, NULL, NULL, NULL, NULL, NULL);
    1940         269 :   if (err)
    1941           0 :     return err;
    1942             : 
    1943         269 :   snprintf (line, sizeof line, "SETKEY %s", keygrip);
    1944         269 :   err = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
    1945         269 :   if (err)
    1946           0 :     return err;
    1947             : 
    1948         269 :   if (desc)
    1949             :     {
    1950         269 :       snprintf (line, DIM(line), "SETKEYDESC %s", desc);
    1951         269 :       err = assuan_transact (agent_ctx, line,
    1952             :                             NULL, NULL, NULL, NULL, NULL, NULL);
    1953         269 :       if (err)
    1954           0 :         return err;
    1955             :     }
    1956             : 
    1957         269 :   init_membuf_secure (&data, 1024);
    1958             :   {
    1959             :     struct cipher_parm_s parm;
    1960             : 
    1961         269 :     parm.dflt = &dfltparm;
    1962         269 :     parm.ctx = agent_ctx;
    1963         269 :     err = make_canon_sexp (s_ciphertext, &parm.ciphertext, &parm.ciphertextlen);
    1964         269 :     if (err)
    1965           0 :       return err;
    1966         269 :     err = assuan_transact (agent_ctx, "PKDECRYPT",
    1967             :                            put_membuf_cb, &data,
    1968             :                            inq_ciphertext_cb, &parm,
    1969             :                            padding_info_cb, r_padding);
    1970         269 :     xfree (parm.ciphertext);
    1971             :   }
    1972         269 :   if (err)
    1973             :     {
    1974           0 :       xfree (get_membuf (&data, &len));
    1975           0 :       return err;
    1976             :     }
    1977             : 
    1978         269 :   put_membuf (&data, "", 1); /* Make sure it is 0 terminated.  */
    1979         269 :   buf = get_membuf (&data, &len);
    1980         269 :   if (!buf)
    1981           0 :     return gpg_error_from_syserror ();
    1982         269 :   log_assert (len); /* (we forced Nul termination.)  */
    1983             : 
    1984         269 :   if (*buf != '(')
    1985             :     {
    1986           0 :       xfree (buf);
    1987           0 :       return gpg_error (GPG_ERR_INV_SEXP);
    1988             :     }
    1989             : 
    1990         269 :   if (len < 13 || memcmp (buf, "(5:value", 8) ) /* "(5:valueN:D)\0" */
    1991             :     {
    1992           0 :       xfree (buf);
    1993           0 :       return gpg_error (GPG_ERR_INV_SEXP);
    1994             :     }
    1995         269 :   len -= 10;   /* Count only the data of the second part. */
    1996         269 :   p = buf + 8; /* Skip leading parenthesis and the value tag. */
    1997             : 
    1998         269 :   n = strtoul (p, &endp, 10);
    1999         269 :   if (!n || *endp != ':')
    2000             :     {
    2001           0 :       xfree (buf);
    2002           0 :       return gpg_error (GPG_ERR_INV_SEXP);
    2003             :     }
    2004         269 :   endp++;
    2005         269 :   if (endp-p+n > len)
    2006             :     {
    2007           0 :       xfree (buf);
    2008           0 :       return gpg_error (GPG_ERR_INV_SEXP); /* Oops: Inconsistent S-Exp. */
    2009             :     }
    2010             : 
    2011         269 :   memmove (buf, endp, n);
    2012             : 
    2013         269 :   *r_buflen = n;
    2014         269 :   *r_buf = buf;
    2015         269 :   return 0;
    2016             : }
    2017             : 
    2018             : 
    2019             : 
    2020             : /* Retrieve a key encryption key from the agent.  With FOREXPORT true
    2021             :    the key shall be used for export, with false for import.  On success
    2022             :    the new key is stored at R_KEY and its length at R_KEKLEN.  */
    2023             : gpg_error_t
    2024          21 : agent_keywrap_key (ctrl_t ctrl, int forexport, void **r_kek, size_t *r_keklen)
    2025             : {
    2026             :   gpg_error_t err;
    2027             :   membuf_t data;
    2028             :   size_t len;
    2029             :   unsigned char *buf;
    2030             :   char line[ASSUAN_LINELENGTH];
    2031             :   struct default_inq_parm_s dfltparm;
    2032             : 
    2033          21 :   memset (&dfltparm, 0, sizeof dfltparm);
    2034          21 :   dfltparm.ctrl = ctrl;
    2035             : 
    2036          21 :   *r_kek = NULL;
    2037          21 :   err = start_agent (ctrl, 0);
    2038          21 :   if (err)
    2039           0 :     return err;
    2040          21 :   dfltparm.ctx = agent_ctx;
    2041             : 
    2042          21 :   snprintf (line, DIM(line), "KEYWRAP_KEY %s",
    2043             :             forexport? "--export":"--import");
    2044             : 
    2045          21 :   init_membuf_secure (&data, 64);
    2046          21 :   err = assuan_transact (agent_ctx, line,
    2047             :                          put_membuf_cb, &data,
    2048             :                          default_inq_cb, &dfltparm,
    2049             :                          NULL, NULL);
    2050          21 :   if (err)
    2051             :     {
    2052           0 :       xfree (get_membuf (&data, &len));
    2053           0 :       return err;
    2054             :     }
    2055          21 :   buf = get_membuf (&data, &len);
    2056          21 :   if (!buf)
    2057           0 :     return gpg_error_from_syserror ();
    2058          21 :   *r_kek = buf;
    2059          21 :   *r_keklen = len;
    2060          21 :   return 0;
    2061             : }
    2062             : 
    2063             : 
    2064             : 
    2065             : /* Handle the inquiry for an IMPORT_KEY command.  */
    2066             : static gpg_error_t
    2067          33 : inq_import_key_parms (void *opaque, const char *line)
    2068             : {
    2069          33 :   struct import_key_parm_s *parm = opaque;
    2070             :   gpg_error_t err;
    2071             : 
    2072          33 :   if (has_leading_keyword (line, "KEYDATA"))
    2073             :     {
    2074          33 :       err = assuan_send_data (parm->dflt->ctx, parm->key, parm->keylen);
    2075             :     }
    2076             :   else
    2077           0 :     err = default_inq_cb (parm->dflt, line);
    2078             : 
    2079          33 :   return err;
    2080             : }
    2081             : 
    2082             : 
    2083             : /* Call the agent to import a key into the agent.  */
    2084             : gpg_error_t
    2085          33 : agent_import_key (ctrl_t ctrl, const char *desc, char **cache_nonce_addr,
    2086             :                   const void *key, size_t keylen, int unattended, int force)
    2087             : {
    2088             :   gpg_error_t err;
    2089             :   struct import_key_parm_s parm;
    2090             :   struct cache_nonce_parm_s cn_parm;
    2091             :   char line[ASSUAN_LINELENGTH];
    2092             :   struct default_inq_parm_s dfltparm;
    2093             : 
    2094          33 :   memset (&dfltparm, 0, sizeof dfltparm);
    2095          33 :   dfltparm.ctrl = ctrl;
    2096             : 
    2097          33 :   err = start_agent (ctrl, 0);
    2098          33 :   if (err)
    2099           0 :     return err;
    2100          33 :   dfltparm.ctx = agent_ctx;
    2101             : 
    2102          33 :   if (desc)
    2103             :     {
    2104          33 :       snprintf (line, DIM(line), "SETKEYDESC %s", desc);
    2105          33 :       err = assuan_transact (agent_ctx, line,
    2106             :                             NULL, NULL, NULL, NULL, NULL, NULL);
    2107          33 :       if (err)
    2108           0 :         return err;
    2109             :     }
    2110             : 
    2111          33 :   parm.dflt   = &dfltparm;
    2112          33 :   parm.key    = key;
    2113          33 :   parm.keylen = keylen;
    2114             : 
    2115          33 :   snprintf (line, sizeof line, "IMPORT_KEY%s%s%s%s",
    2116             :             unattended? " --unattended":"",
    2117             :             force? " --force":"",
    2118          33 :             cache_nonce_addr && *cache_nonce_addr? " ":"",
    2119          33 :             cache_nonce_addr && *cache_nonce_addr? *cache_nonce_addr:"");
    2120          33 :   cn_parm.cache_nonce_addr = cache_nonce_addr;
    2121          33 :   cn_parm.passwd_nonce_addr = NULL;
    2122          33 :   err = assuan_transact (agent_ctx, line,
    2123             :                          NULL, NULL,
    2124             :                          inq_import_key_parms, &parm,
    2125             :                          cache_nonce_status_cb, &cn_parm);
    2126          33 :   return err;
    2127             : }
    2128             : 
    2129             : 
    2130             : 
    2131             : /* Receive a secret key from the agent.  HEXKEYGRIP is the hexified
    2132             :    keygrip, DESC a prompt to be displayed with the agent's passphrase
    2133             :    question (needs to be plus+percent escaped).  if OPENPGP_PROTECTED
    2134             :    is not zero, ensure that the key material is returned in RFC
    2135             :    4880-compatible passphrased-protected form.  If CACHE_NONCE_ADDR is
    2136             :    not NULL the agent is advised to first try a passphrase associated
    2137             :    with that nonce.  On success the key is stored as a canonical
    2138             :    S-expression at R_RESULT and R_RESULTLEN.  */
    2139             : gpg_error_t
    2140           5 : agent_export_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
    2141             :                   int openpgp_protected, char **cache_nonce_addr,
    2142             :                   unsigned char **r_result, size_t *r_resultlen)
    2143             : {
    2144             :   gpg_error_t err;
    2145             :   struct cache_nonce_parm_s cn_parm;
    2146             :   membuf_t data;
    2147             :   size_t len;
    2148             :   unsigned char *buf;
    2149             :   char line[ASSUAN_LINELENGTH];
    2150             :   struct default_inq_parm_s dfltparm;
    2151             : 
    2152           5 :   memset (&dfltparm, 0, sizeof dfltparm);
    2153           5 :   dfltparm.ctrl = ctrl;
    2154             : 
    2155           5 :   *r_result = NULL;
    2156             : 
    2157           5 :   err = start_agent (ctrl, 0);
    2158           5 :   if (err)
    2159           0 :     return err;
    2160           5 :   dfltparm.ctx = agent_ctx;
    2161             : 
    2162           5 :   if (desc)
    2163             :     {
    2164           5 :       snprintf (line, DIM(line), "SETKEYDESC %s", desc);
    2165           5 :       err = assuan_transact (agent_ctx, line,
    2166             :                              NULL, NULL, NULL, NULL, NULL, NULL);
    2167           5 :       if (err)
    2168           0 :         return err;
    2169             :     }
    2170             : 
    2171           7 :   snprintf (line, DIM(line), "EXPORT_KEY %s%s%s %s",
    2172             :             openpgp_protected ? "--openpgp ":"",
    2173           5 :             cache_nonce_addr && *cache_nonce_addr? "--cache-nonce=":"",
    2174           5 :             cache_nonce_addr && *cache_nonce_addr? *cache_nonce_addr:"",
    2175             :             hexkeygrip);
    2176             : 
    2177           5 :   init_membuf_secure (&data, 1024);
    2178           5 :   cn_parm.cache_nonce_addr = cache_nonce_addr;
    2179           5 :   cn_parm.passwd_nonce_addr = NULL;
    2180           5 :   err = assuan_transact (agent_ctx, line,
    2181             :                          put_membuf_cb, &data,
    2182             :                          default_inq_cb, &dfltparm,
    2183             :                          cache_nonce_status_cb, &cn_parm);
    2184           5 :   if (err)
    2185             :     {
    2186           0 :       xfree (get_membuf (&data, &len));
    2187           0 :       return err;
    2188             :     }
    2189           5 :   buf = get_membuf (&data, &len);
    2190           5 :   if (!buf)
    2191           0 :     return gpg_error_from_syserror ();
    2192           5 :   *r_result = buf;
    2193           5 :   *r_resultlen = len;
    2194           5 :   return 0;
    2195             : }
    2196             : 
    2197             : 
    2198             : 
    2199             : /* Ask the agent to delete the key identified by HEXKEYGRIP.  If DESC
    2200             :    is not NULL, display DESC instead of the default description
    2201             :    message.  If FORCE is true the agent is advised not to ask for
    2202             :    confirmation. */
    2203             : gpg_error_t
    2204           0 : agent_delete_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
    2205             :                   int force)
    2206             : {
    2207             :   gpg_error_t err;
    2208             :   char line[ASSUAN_LINELENGTH];
    2209             :   struct default_inq_parm_s dfltparm;
    2210             : 
    2211           0 :   memset (&dfltparm, 0, sizeof dfltparm);
    2212           0 :   dfltparm.ctrl = ctrl;
    2213             : 
    2214           0 :   err = start_agent (ctrl, 0);
    2215           0 :   if (err)
    2216           0 :     return err;
    2217             : 
    2218           0 :   if (!hexkeygrip || strlen (hexkeygrip) != 40)
    2219           0 :     return gpg_error (GPG_ERR_INV_VALUE);
    2220             : 
    2221           0 :   if (desc)
    2222             :     {
    2223           0 :       snprintf (line, DIM(line), "SETKEYDESC %s", desc);
    2224           0 :       err = assuan_transact (agent_ctx, line,
    2225             :                              NULL, NULL, NULL, NULL, NULL, NULL);
    2226           0 :       if (err)
    2227           0 :         return err;
    2228             :     }
    2229             : 
    2230           0 :   snprintf (line, DIM(line), "DELETE_KEY%s %s",
    2231             :             force? " --force":"", hexkeygrip);
    2232           0 :   err = assuan_transact (agent_ctx, line, NULL, NULL,
    2233             :                          default_inq_cb, &dfltparm,
    2234             :                          NULL, NULL);
    2235           0 :   return err;
    2236             : }
    2237             : 
    2238             : 
    2239             : 
    2240             : /* Ask the agent to change the passphrase of the key identified by
    2241             :  * HEXKEYGRIP.  If DESC is not NULL, display DESC instead of the
    2242             :  * default description message.  If CACHE_NONCE_ADDR is not NULL the
    2243             :  * agent is advised to first try a passphrase associated with that
    2244             :  * nonce.  If PASSWD_NONCE_ADDR is not NULL the agent will try to use
    2245             :  * the passphrase associated with that nonce for the new passphrase.
    2246             :  * If VERIFY is true the passphrase is only verified.  */
    2247             : gpg_error_t
    2248           0 : agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc, int verify,
    2249             :               char **cache_nonce_addr, char **passwd_nonce_addr)
    2250             : {
    2251             :   gpg_error_t err;
    2252             :   struct cache_nonce_parm_s cn_parm;
    2253             :   char line[ASSUAN_LINELENGTH];
    2254             :   struct default_inq_parm_s dfltparm;
    2255             : 
    2256           0 :   memset (&dfltparm, 0, sizeof dfltparm);
    2257           0 :   dfltparm.ctrl = ctrl;
    2258             : 
    2259           0 :   err = start_agent (ctrl, 0);
    2260           0 :   if (err)
    2261           0 :     return err;
    2262           0 :   dfltparm.ctx = agent_ctx;
    2263             : 
    2264           0 :   if (!hexkeygrip || strlen (hexkeygrip) != 40)
    2265           0 :     return gpg_error (GPG_ERR_INV_VALUE);
    2266             : 
    2267           0 :   if (desc)
    2268             :     {
    2269           0 :       snprintf (line, DIM(line), "SETKEYDESC %s", desc);
    2270           0 :       err = assuan_transact (agent_ctx, line,
    2271             :                              NULL, NULL, NULL, NULL, NULL, NULL);
    2272           0 :       if (err)
    2273           0 :         return err;
    2274             :     }
    2275             : 
    2276           0 :   if (verify)
    2277           0 :     snprintf (line, DIM(line), "PASSWD %s%s --verify %s",
    2278           0 :               cache_nonce_addr && *cache_nonce_addr? "--cache-nonce=":"",
    2279           0 :               cache_nonce_addr && *cache_nonce_addr? *cache_nonce_addr:"",
    2280             :               hexkeygrip);
    2281             :   else
    2282           0 :     snprintf (line, DIM(line), "PASSWD %s%s %s%s %s",
    2283           0 :               cache_nonce_addr && *cache_nonce_addr? "--cache-nonce=":"",
    2284           0 :               cache_nonce_addr && *cache_nonce_addr? *cache_nonce_addr:"",
    2285           0 :               passwd_nonce_addr && *passwd_nonce_addr? "--passwd-nonce=":"",
    2286           0 :               passwd_nonce_addr && *passwd_nonce_addr? *passwd_nonce_addr:"",
    2287             :               hexkeygrip);
    2288           0 :   cn_parm.cache_nonce_addr = cache_nonce_addr;
    2289           0 :   cn_parm.passwd_nonce_addr = passwd_nonce_addr;
    2290           0 :   err = assuan_transact (agent_ctx, line, NULL, NULL,
    2291             :                          default_inq_cb, &dfltparm,
    2292             :                          cache_nonce_status_cb, &cn_parm);
    2293           0 :   return err;
    2294             : }
    2295             : 
    2296             : 
    2297             : /* Return the version reported by gpg-agent.  */
    2298             : gpg_error_t
    2299           3 : agent_get_version (ctrl_t ctrl, char **r_version)
    2300             : {
    2301             :   gpg_error_t err;
    2302             : 
    2303           3 :   err = start_agent (ctrl, 0);
    2304           3 :   if (err)
    2305           0 :     return err;
    2306             : 
    2307           3 :   err = get_assuan_server_version (agent_ctx, 0, r_version);
    2308           3 :   return err;
    2309             : }

Generated by: LCOV version 1.11