LCOV - code coverage report
Current view: top level - g10 - call-agent.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 229 1072 21.4 %
Date: 2015-11-05 17:10:59 Functions: 15 52 28.8 %

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

Generated by: LCOV version 1.11