LCOV - code coverage report
Current view: top level - g10 - call-agent.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 306 1082 28.3 %
Date: 2016-09-12 12:29:17 Functions: 21 52 40.4 %

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

Generated by: LCOV version 1.11