LCOV - code coverage report
Current view: top level - agent - findkey.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 307 690 44.5 %
Date: 2016-09-12 12:29:17 Functions: 13 17 76.5 %

          Line data    Source code
       1             : /* findkey.c - Locate the secret key
       2             :  * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007,
       3             :  *               2010, 2011 Free Software Foundation, Inc.
       4             :  * Copyright (C) 2014 Werner Koch
       5             :  *
       6             :  * This file is part of GnuPG.
       7             :  *
       8             :  * GnuPG is free software; you can redistribute it and/or modify
       9             :  * it under the terms of the GNU General Public License as published by
      10             :  * the Free Software Foundation; either version 3 of the License, or
      11             :  * (at your option) any later version.
      12             :  *
      13             :  * GnuPG is distributed in the hope that it will be useful,
      14             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :  * GNU General Public License for more details.
      17             :  *
      18             :  * You should have received a copy of the GNU General Public License
      19             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      20             :  */
      21             : 
      22             : #include <config.h>
      23             : #include <errno.h>
      24             : #include <stdio.h>
      25             : #include <stdlib.h>
      26             : #include <string.h>
      27             : #include <ctype.h>
      28             : #include <fcntl.h>
      29             : #include <assert.h>
      30             : #include <unistd.h>
      31             : #include <sys/stat.h>
      32             : #include <assert.h>
      33             : #include <npth.h> /* (we use pth_sleep) */
      34             : 
      35             : #include "agent.h"
      36             : #include "i18n.h"
      37             : #include "../common/ssh-utils.h"
      38             : #include "../common/name-value.h"
      39             : 
      40             : #ifndef O_BINARY
      41             : #define O_BINARY 0
      42             : #endif
      43             : 
      44             : /* Helper to pass data to the check callback of the unprotect function. */
      45             : struct try_unprotect_arg_s
      46             : {
      47             :   ctrl_t ctrl;
      48             :   const unsigned char *protected_key;
      49             :   unsigned char *unprotected_key;
      50             :   int change_required; /* Set by the callback to indicate that the
      51             :                           user should change the passphrase.  */
      52             : };
      53             : 
      54             : 
      55             : static gpg_error_t
      56           0 : write_extended_private_key (char *fname, estream_t fp,
      57             :                             const void *buf, size_t len)
      58             : {
      59             :   gpg_error_t err;
      60           0 :   nvc_t pk = NULL;
      61           0 :   gcry_sexp_t key = NULL;
      62           0 :   int remove = 0;
      63             :   int line;
      64             : 
      65           0 :   err = nvc_parse_private_key (&pk, &line, fp);
      66           0 :   if (err)
      67             :     {
      68           0 :       log_error ("error parsing '%s' line %d: %s\n",
      69             :                  fname, line, gpg_strerror (err));
      70           0 :       goto leave;
      71             :     }
      72             : 
      73           0 :   err = gcry_sexp_sscan (&key, NULL, buf, len);
      74           0 :   if (err)
      75           0 :     goto leave;
      76             : 
      77           0 :   err = nvc_set_private_key (pk, key);
      78           0 :   if (err)
      79           0 :     goto leave;
      80             : 
      81           0 :   err = es_fseek (fp, 0, SEEK_SET);
      82           0 :   if (err)
      83           0 :     goto leave;
      84             : 
      85           0 :   err = nvc_write (pk, fp);
      86           0 :   if (err)
      87             :     {
      88           0 :       log_error ("error writing '%s': %s\n", fname, gpg_strerror (err));
      89           0 :       remove = 1;
      90           0 :       goto leave;
      91             :     }
      92             : 
      93           0 :   if (ftruncate (es_fileno (fp), es_ftello (fp)))
      94             :     {
      95           0 :       err = gpg_error_from_syserror ();
      96           0 :       log_error ("error truncating '%s': %s\n", fname, gpg_strerror (err));
      97           0 :       remove = 1;
      98           0 :       goto leave;
      99             :     }
     100             : 
     101           0 :   if (es_fclose (fp))
     102             :     {
     103           0 :       err = gpg_error_from_syserror ();
     104           0 :       log_error ("error closing '%s': %s\n", fname, gpg_strerror (err));
     105           0 :       remove = 1;
     106           0 :       goto leave;
     107             :     }
     108             :   else
     109           0 :     fp = NULL;
     110             : 
     111           0 :   bump_key_eventcounter ();
     112             : 
     113             :  leave:
     114           0 :   if (fp)
     115           0 :     es_fclose (fp);
     116           0 :   if (remove)
     117           0 :     gnupg_remove (fname);
     118           0 :   xfree (fname);
     119           0 :   gcry_sexp_release (key);
     120           0 :   nvc_release (pk);
     121           0 :   return err;
     122             : }
     123             : 
     124             : /* Write an S-expression formatted key to our key storage.  With FORCE
     125             :    passed as true an existing key with the given GRIP will get
     126             :    overwritten.  */
     127             : int
     128          34 : agent_write_private_key (const unsigned char *grip,
     129             :                          const void *buffer, size_t length, int force)
     130             : {
     131             :   char *fname;
     132             :   estream_t fp;
     133             :   char hexgrip[40+4+1];
     134             : 
     135          34 :   bin2hex (grip, 20, hexgrip);
     136          34 :   strcpy (hexgrip+40, ".key");
     137             : 
     138          34 :   fname = make_filename (gnupg_homedir (), GNUPG_PRIVATE_KEYS_DIR,
     139             :                          hexgrip, NULL);
     140             : 
     141             :   /* FIXME: Write to a temp file first so that write failures during
     142             :      key updates won't lead to a key loss.  */
     143             : 
     144          34 :   if (!force && !access (fname, F_OK))
     145             :     {
     146           0 :       log_error ("secret key file '%s' already exists\n", fname);
     147           0 :       xfree (fname);
     148           0 :       return gpg_error (GPG_ERR_EEXIST);
     149             :     }
     150             : 
     151          34 :   fp = es_fopen (fname, force? "rb+,mode=-rw" : "wbx,mode=-rw");
     152          34 :   if (!fp)
     153             :     {
     154           0 :       gpg_error_t tmperr = gpg_error_from_syserror ();
     155           0 :       log_error ("can't create '%s': %s\n", fname, gpg_strerror (tmperr));
     156           0 :       xfree (fname);
     157           0 :       return tmperr;
     158             :     }
     159             : 
     160             :   /* See if an existing key is in extended format.  */
     161          34 :   if (force)
     162             :     {
     163             :       gpg_error_t rc;
     164             :       char first;
     165             : 
     166           8 :       if (es_fread (&first, 1, 1, fp) != 1)
     167             :         {
     168           0 :           rc = gpg_error_from_syserror ();
     169           0 :           log_error ("error reading first byte from '%s': %s\n",
     170           0 :                      fname, strerror (errno));
     171           0 :           xfree (fname);
     172           0 :           es_fclose (fp);
     173           0 :           return rc;
     174             :         }
     175             : 
     176           8 :       rc = es_fseek (fp, 0, SEEK_SET);
     177           8 :       if (rc)
     178             :         {
     179           0 :           log_error ("error seeking in '%s': %s\n", fname, strerror (errno));
     180           0 :           xfree (fname);
     181           0 :           es_fclose (fp);
     182           0 :           return rc;
     183             :         }
     184             : 
     185           8 :       if (first != '(')
     186             :         {
     187             :           /* Key is in extended format.  */
     188           0 :           return write_extended_private_key (fname, fp, buffer, length);
     189             :         }
     190             :     }
     191             : 
     192          34 :   if (es_fwrite (buffer, length, 1, fp) != 1)
     193             :     {
     194           0 :       gpg_error_t tmperr = gpg_error_from_syserror ();
     195           0 :       log_error ("error writing '%s': %s\n", fname, gpg_strerror (tmperr));
     196           0 :       es_fclose (fp);
     197           0 :       gnupg_remove (fname);
     198           0 :       xfree (fname);
     199           0 :       return tmperr;
     200             :     }
     201             : 
     202             :   /* When force is given, the file might have to be truncated.  */
     203          34 :   if (force && ftruncate (es_fileno (fp), es_ftello (fp)))
     204             :     {
     205           0 :       gpg_error_t tmperr = gpg_error_from_syserror ();
     206           0 :       log_error ("error truncating '%s': %s\n", fname, gpg_strerror (tmperr));
     207           0 :       es_fclose (fp);
     208           0 :       gnupg_remove (fname);
     209           0 :       xfree (fname);
     210           0 :       return tmperr;
     211             :     }
     212             : 
     213          34 :   if (es_fclose (fp))
     214             :     {
     215           0 :       gpg_error_t tmperr = gpg_error_from_syserror ();
     216           0 :       log_error ("error closing '%s': %s\n", fname, gpg_strerror (tmperr));
     217           0 :       gnupg_remove (fname);
     218           0 :       xfree (fname);
     219           0 :       return tmperr;
     220             :     }
     221          34 :   bump_key_eventcounter ();
     222          34 :   xfree (fname);
     223          34 :   return 0;
     224             : }
     225             : 
     226             : 
     227             : /* Callback function to try the unprotection from the passphrase query
     228             :    code. */
     229             : static gpg_error_t
     230           1 : try_unprotect_cb (struct pin_entry_info_s *pi)
     231             : {
     232           1 :   struct try_unprotect_arg_s *arg = pi->check_cb_arg;
     233           1 :   ctrl_t ctrl = arg->ctrl;
     234             :   size_t dummy;
     235             :   gpg_error_t err;
     236             :   gnupg_isotime_t now, protected_at, tmptime;
     237           1 :   char *desc = NULL;
     238             : 
     239           1 :   assert (!arg->unprotected_key);
     240             : 
     241           1 :   arg->change_required = 0;
     242           1 :   err = agent_unprotect (ctrl, arg->protected_key, pi->pin, protected_at,
     243             :                          &arg->unprotected_key, &dummy);
     244           1 :   if (err)
     245           0 :     return err;
     246           1 :   if (!opt.max_passphrase_days || ctrl->in_passwd)
     247           1 :     return 0;  /* No regular passphrase change required.  */
     248             : 
     249           0 :   if (!*protected_at)
     250             :     {
     251             :       /* No protection date known - must force passphrase change.  */
     252           0 :       desc = xtrystrdup (L_("Note: This passphrase has never been changed.%0A"
     253             :                             "Please change it now."));
     254           0 :       if (!desc)
     255           0 :         return gpg_error_from_syserror ();
     256             :     }
     257             :   else
     258             :     {
     259           0 :       gnupg_get_isotime (now);
     260           0 :       gnupg_copy_time (tmptime, protected_at);
     261           0 :       err = add_days_to_isotime (tmptime, opt.max_passphrase_days);
     262           0 :       if (err)
     263           0 :         return err;
     264           0 :       if (strcmp (now, tmptime) > 0 )
     265             :         {
     266             :           /* Passphrase "expired".  */
     267           0 :           desc = xtryasprintf
     268             :             (L_("This passphrase has not been changed%%0A"
     269             :                 "since %.4s-%.2s-%.2s.  Please change it now."),
     270             :              protected_at, protected_at+4, protected_at+6);
     271           0 :           if (!desc)
     272           0 :             return gpg_error_from_syserror ();
     273             :         }
     274             :     }
     275             : 
     276           0 :   if (desc)
     277             :     {
     278             :       /* Change required.  */
     279           0 :       if (opt.enforce_passphrase_constraints)
     280             :         {
     281           0 :           err = agent_get_confirmation (ctrl, desc,
     282             :                                         L_("Change passphrase"), NULL, 0);
     283           0 :           if (!err)
     284           0 :             arg->change_required = 1;
     285             :         }
     286             :       else
     287             :         {
     288           0 :           err = agent_get_confirmation (ctrl, desc,
     289             :                                         L_("Change passphrase"),
     290             :                                         L_("I'll change it later"), 0);
     291           0 :           if (!err)
     292           0 :             arg->change_required = 1;
     293           0 :           else if (gpg_err_code (err) == GPG_ERR_CANCELED
     294           0 :                    || gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
     295           0 :             err = 0;
     296             :         }
     297           0 :       xfree (desc);
     298             :     }
     299             : 
     300           0 :   return 0;
     301             : }
     302             : 
     303             : 
     304             : /* Modify a Key description, replacing certain special format
     305             :    characters.  List of currently supported replacements:
     306             : 
     307             :    %% - Replaced by a single %
     308             :    %c - Replaced by the content of COMMENT.
     309             :    %C - Same as %c but put into parentheses.
     310             :    %F - Replaced by an ssh style fingerprint computed from KEY.
     311             : 
     312             :    The functions returns 0 on success or an error code.  On success a
     313             :    newly allocated string is stored at the address of RESULT.
     314             :  */
     315             : static gpg_error_t
     316         137 : modify_description (const char *in, const char *comment, const gcry_sexp_t key,
     317             :                     char **result)
     318             : {
     319             :   size_t comment_length;
     320             :   size_t in_len;
     321             :   size_t out_len;
     322             :   char *out;
     323             :   size_t i;
     324             :   int special, pass;
     325         137 :   char *ssh_fpr = NULL;
     326             : 
     327         137 :   comment_length = strlen (comment);
     328         137 :   in_len  = strlen (in);
     329             : 
     330             :   /* First pass calculates the length, second pass does the actual
     331             :      copying.  */
     332         137 :   out = NULL;
     333         137 :   out_len = 0;
     334         411 :   for (pass=0; pass < 2; pass++)
     335             :     {
     336         274 :       special = 0;
     337       49814 :       for (i = 0; i < in_len; i++)
     338             :         {
     339       49540 :           if (special)
     340             :             {
     341        1644 :               special = 0;
     342        1644 :               switch (in[i])
     343             :                 {
     344             :                 case '%':
     345           0 :                   if (out)
     346           0 :                     *out++ = '%';
     347             :                   else
     348           0 :                     out_len++;
     349           0 :                   break;
     350             : 
     351             :                 case 'c': /* Comment.  */
     352           0 :                   if (out)
     353             :                     {
     354           0 :                       memcpy (out, comment, comment_length);
     355           0 :                       out += comment_length;
     356             :                     }
     357             :                   else
     358           0 :                     out_len += comment_length;
     359           0 :                   break;
     360             : 
     361             :                 case 'C': /* Comment.  */
     362           0 :                   if (!comment_length)
     363             :                     ;
     364           0 :                   else if (out)
     365             :                     {
     366           0 :                       *out++ = '(';
     367           0 :                       memcpy (out, comment, comment_length);
     368           0 :                       out += comment_length;
     369           0 :                       *out++ = ')';
     370             :                     }
     371             :                   else
     372           0 :                     out_len += comment_length + 2;
     373           0 :                   break;
     374             : 
     375             :                 case 'F': /* SSH style fingerprint.  */
     376           0 :                   if (!ssh_fpr && key)
     377           0 :                     ssh_get_fingerprint_string (key, &ssh_fpr);
     378           0 :                   if (ssh_fpr)
     379             :                     {
     380           0 :                       if (out)
     381           0 :                         out = stpcpy (out, ssh_fpr);
     382             :                       else
     383           0 :                         out_len += strlen (ssh_fpr);
     384             :                     }
     385           0 :                   break;
     386             : 
     387             :                 default: /* Invalid special sequences are kept as they are. */
     388        1644 :                   if (out)
     389             :                     {
     390         822 :                       *out++ = '%';
     391         822 :                       *out++ = in[i];
     392             :                     }
     393             :                   else
     394         822 :                     out_len+=2;
     395        1644 :                   break;
     396             :                 }
     397             :             }
     398       47896 :           else if (in[i] == '%')
     399        1644 :             special = 1;
     400             :           else
     401             :             {
     402       46252 :               if (out)
     403       23126 :                 *out++ = in[i];
     404             :               else
     405       23126 :                 out_len++;
     406             :             }
     407             :         }
     408             : 
     409         274 :       if (!pass)
     410             :         {
     411         137 :           *result = out = xtrymalloc (out_len + 1);
     412         137 :           if (!out)
     413             :             {
     414           0 :               xfree (ssh_fpr);
     415           0 :               return gpg_error_from_syserror ();
     416             :             }
     417             :         }
     418             :     }
     419             : 
     420         137 :   *out = 0;
     421         137 :   assert (*result + out_len == out);
     422         137 :   xfree (ssh_fpr);
     423         137 :   return 0;
     424             : }
     425             : 
     426             : 
     427             : 
     428             : /* Unprotect the canconical encoded S-expression key in KEYBUF.  GRIP
     429             :    should be the hex encoded keygrip of that key to be used with the
     430             :    caching mechanism. DESC_TEXT may be set to override the default
     431             :    description used for the pinentry.  If LOOKUP_TTL is given this
     432             :    function is used to lookup the default ttl.  If R_PASSPHRASE is not
     433             :    NULL, the function succeeded and the key was protected the used
     434             :    passphrase (entered or from the cache) is stored there; if not NULL
     435             :    will be stored.  The caller needs to free the returned
     436             :    passphrase. */
     437             : static int
     438         137 : unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
     439             :            unsigned char **keybuf, const unsigned char *grip,
     440             :            cache_mode_t cache_mode, lookup_ttl_t lookup_ttl,
     441             :            char **r_passphrase)
     442             : {
     443             :   struct pin_entry_info_s *pi;
     444             :   struct try_unprotect_arg_s arg;
     445             :   int rc;
     446             :   unsigned char *result;
     447             :   size_t resultlen;
     448             :   char hexgrip[40+1];
     449             : 
     450         137 :   if (r_passphrase)
     451           2 :     *r_passphrase = NULL;
     452             : 
     453         137 :   bin2hex (grip, 20, hexgrip);
     454             : 
     455             :   /* Initially try to get it using a cache nonce.  */
     456         137 :   if (cache_nonce)
     457             :     {
     458             :       char *pw;
     459             : 
     460           1 :       pw = agent_get_cache (cache_nonce, CACHE_MODE_NONCE);
     461           1 :       if (pw)
     462             :         {
     463           1 :           rc = agent_unprotect (ctrl, *keybuf, pw, NULL, &result, &resultlen);
     464           1 :           if (!rc)
     465             :             {
     466           1 :               if (r_passphrase)
     467           1 :                 *r_passphrase = pw;
     468             :               else
     469           0 :                 xfree (pw);
     470           1 :               xfree (*keybuf);
     471           1 :               *keybuf = result;
     472           1 :               return 0;
     473             :             }
     474           0 :           xfree (pw);
     475             :         }
     476             :     }
     477             : 
     478             :   /* First try to get it from the cache - if there is none or we can't
     479             :      unprotect it, we fall back to ask the user */
     480         136 :   if (cache_mode != CACHE_MODE_IGNORE)
     481             :     {
     482             :       char *pw;
     483             : 
     484             :     retry:
     485         135 :       pw = agent_get_cache (hexgrip, cache_mode);
     486         135 :       if (pw)
     487             :         {
     488         135 :           rc = agent_unprotect (ctrl, *keybuf, pw, NULL, &result, &resultlen);
     489         135 :           if (!rc)
     490             :             {
     491         135 :               if (cache_mode == CACHE_MODE_NORMAL)
     492         135 :                 agent_store_cache_hit (hexgrip);
     493         135 :               if (r_passphrase)
     494           0 :                 *r_passphrase = pw;
     495             :               else
     496         135 :                 xfree (pw);
     497         135 :               xfree (*keybuf);
     498         135 :               *keybuf = result;
     499         135 :               return 0;
     500             :             }
     501           0 :           xfree (pw);
     502           0 :           rc  = 0;
     503             :         }
     504           0 :       else if (cache_mode == CACHE_MODE_NORMAL)
     505             :         {
     506             :           /* The standard use of GPG keys is to have a signing and an
     507             :              encryption subkey.  Commonly both use the same
     508             :              passphrase.  We try to help the user to enter the
     509             :              passphrase only once by silently trying the last
     510             :              correctly entered passphrase.  Checking one additional
     511             :              passphrase should be acceptable; despite the S2K
     512             :              introduced delays. The assumed workflow is:
     513             : 
     514             :                1. Read encrypted message in a MUA and thus enter a
     515             :                   passphrase for the encryption subkey.
     516             : 
     517             :                2. Reply to that mail with an encrypted and signed
     518             :                   mail, thus entering the passphrase for the signing
     519             :                   subkey.
     520             : 
     521             :              We can often avoid the passphrase entry in the second
     522             :              step.  We do this only in normal mode, so not to
     523             :              interfere with unrelated cache entries.  */
     524           0 :           pw = agent_get_cache (NULL, cache_mode);
     525           0 :           if (pw)
     526             :             {
     527           0 :               rc = agent_unprotect (ctrl, *keybuf, pw, NULL,
     528             :                                     &result, &resultlen);
     529           0 :               if (!rc)
     530             :                 {
     531           0 :                   if (r_passphrase)
     532           0 :                     *r_passphrase = pw;
     533             :                   else
     534           0 :                     xfree (pw);
     535           0 :                   xfree (*keybuf);
     536           0 :                   *keybuf = result;
     537           0 :                   return 0;
     538             :                 }
     539           0 :               xfree (pw);
     540           0 :               rc  = 0;
     541             :             }
     542             :         }
     543             : 
     544             :       /* If the pinentry is currently in use, we wait up to 60 seconds
     545             :          for it to close and check the cache again.  This solves a common
     546             :          situation where several requests for unprotecting a key have
     547             :          been made but the user is still entering the passphrase for
     548             :          the first request.  Because all requests to agent_askpin are
     549             :          serialized they would then pop up one after the other to
     550             :          request the passphrase - despite that the user has already
     551             :          entered it and is then available in the cache.  This
     552             :          implementation is not race free but in the worst case the
     553             :          user has to enter the passphrase only once more. */
     554           0 :       if (pinentry_active_p (ctrl, 0))
     555             :         {
     556             :           /* Active - wait */
     557           0 :           if (!pinentry_active_p (ctrl, 60))
     558             :             {
     559             :               /* We need to give the other thread a chance to actually put
     560             :                  it into the cache. */
     561           0 :               npth_sleep (1);
     562           0 :               goto retry;
     563             :             }
     564             :           /* Timeout - better call pinentry now the plain way. */
     565             :         }
     566             :     }
     567             : 
     568           1 :   pi = gcry_calloc_secure (1, sizeof (*pi) + MAX_PASSPHRASE_LEN + 1);
     569           1 :   if (!pi)
     570           0 :     return gpg_error_from_syserror ();
     571           1 :   pi->max_length = MAX_PASSPHRASE_LEN + 1;
     572           1 :   pi->min_digits = 0;  /* we want a real passphrase */
     573           1 :   pi->max_digits = 16;
     574           1 :   pi->max_tries = 3;
     575           1 :   pi->check_cb = try_unprotect_cb;
     576           1 :   arg.ctrl = ctrl;
     577           1 :   arg.protected_key = *keybuf;
     578           1 :   arg.unprotected_key = NULL;
     579           1 :   arg.change_required = 0;
     580           1 :   pi->check_cb_arg = &arg;
     581             : 
     582           1 :   rc = agent_askpin (ctrl, desc_text, NULL, NULL, pi, hexgrip, cache_mode);
     583           1 :   if (!rc)
     584             :     {
     585           1 :       assert (arg.unprotected_key);
     586           1 :       if (arg.change_required)
     587             :         {
     588             :           /* The callback told as that the user should change their
     589             :              passphrase.  Present the dialog to do.  */
     590             :           size_t canlen, erroff;
     591             :           gcry_sexp_t s_skey;
     592             : 
     593           0 :           assert (arg.unprotected_key);
     594           0 :           canlen = gcry_sexp_canon_len (arg.unprotected_key, 0, NULL, NULL);
     595           0 :           rc = gcry_sexp_sscan (&s_skey, &erroff,
     596           0 :                                 (char*)arg.unprotected_key, canlen);
     597           0 :           if (rc)
     598             :             {
     599           0 :               log_error ("failed to build S-Exp (off=%u): %s\n",
     600             :                          (unsigned int)erroff, gpg_strerror (rc));
     601           0 :               wipememory (arg.unprotected_key, canlen);
     602           0 :               xfree (arg.unprotected_key);
     603           0 :               xfree (pi);
     604           0 :               return rc;
     605             :             }
     606           0 :           rc = agent_protect_and_store (ctrl, s_skey, NULL);
     607           0 :           gcry_sexp_release (s_skey);
     608           0 :           if (rc)
     609             :             {
     610           0 :               log_error ("changing the passphrase failed: %s\n",
     611             :                          gpg_strerror (rc));
     612           0 :               wipememory (arg.unprotected_key, canlen);
     613           0 :               xfree (arg.unprotected_key);
     614           0 :               xfree (pi);
     615           0 :               return rc;
     616             :             }
     617             :         }
     618             :       else
     619             :         {
     620             :           /* Passphrase is fine.  */
     621           1 :           agent_put_cache (hexgrip, cache_mode, pi->pin,
     622             :                            lookup_ttl? lookup_ttl (hexgrip) : 0);
     623           1 :           agent_store_cache_hit (hexgrip);
     624           1 :           if (r_passphrase && *pi->pin)
     625           1 :             *r_passphrase = xtrystrdup (pi->pin);
     626             :         }
     627           1 :       xfree (*keybuf);
     628           1 :       *keybuf = arg.unprotected_key;
     629             :     }
     630           1 :   xfree (pi);
     631           1 :   return rc;
     632             : }
     633             : 
     634             : 
     635             : /* Read the key identified by GRIP from the private key directory and
     636             :    return it as an gcrypt S-expression object in RESULT.  On failure
     637             :    returns an error code and stores NULL at RESULT. */
     638             : static gpg_error_t
     639         440 : read_key_file (const unsigned char *grip, gcry_sexp_t *result)
     640             : {
     641             :   int rc;
     642             :   char *fname;
     643             :   estream_t fp;
     644             :   struct stat st;
     645             :   unsigned char *buf;
     646             :   size_t buflen, erroff;
     647             :   gcry_sexp_t s_skey;
     648             :   char hexgrip[40+4+1];
     649             :   char first;
     650             : 
     651         440 :   *result = NULL;
     652             : 
     653         440 :   bin2hex (grip, 20, hexgrip);
     654         440 :   strcpy (hexgrip+40, ".key");
     655             : 
     656         440 :   fname = make_filename (gnupg_homedir (), GNUPG_PRIVATE_KEYS_DIR,
     657             :                          hexgrip, NULL);
     658         440 :   fp = es_fopen (fname, "rb");
     659         440 :   if (!fp)
     660             :     {
     661           0 :       rc = gpg_error_from_syserror ();
     662           0 :       if (gpg_err_code (rc) != GPG_ERR_ENOENT)
     663           0 :         log_error ("can't open '%s': %s\n", fname, strerror (errno));
     664           0 :       xfree (fname);
     665           0 :       return rc;
     666             :     }
     667             : 
     668         440 :   if (es_fread (&first, 1, 1, fp) != 1)
     669             :     {
     670           0 :       rc = gpg_error_from_syserror ();
     671           0 :       log_error ("error reading first byte from '%s': %s\n",
     672           0 :                  fname, strerror (errno));
     673           0 :       xfree (fname);
     674           0 :       es_fclose (fp);
     675           0 :       return rc;
     676             :     }
     677             : 
     678         440 :   rc = es_fseek (fp, 0, SEEK_SET);
     679         440 :   if (rc)
     680             :     {
     681           0 :       log_error ("error seeking in '%s': %s\n", fname, strerror (errno));
     682           0 :       xfree (fname);
     683           0 :       es_fclose (fp);
     684           0 :       return rc;
     685             :     }
     686             : 
     687         440 :   if (first != '(')
     688             :     {
     689             :       /* Key is in extended format.  */
     690             :       nvc_t pk;
     691             :       int line;
     692             : 
     693           0 :       rc = nvc_parse_private_key (&pk, &line, fp);
     694           0 :       es_fclose (fp);
     695             : 
     696           0 :       if (rc)
     697           0 :         log_error ("error parsing '%s' line %d: %s\n",
     698             :                    fname, line, gpg_strerror (rc));
     699             :       else
     700             :         {
     701           0 :           rc = nvc_get_private_key (pk, result);
     702           0 :           nvc_release (pk);
     703           0 :           if (rc)
     704           0 :             log_error ("error getting private key from '%s': %s\n",
     705             :                        fname, gpg_strerror (rc));
     706             :         }
     707             : 
     708           0 :       xfree (fname);
     709           0 :       return rc;
     710             :     }
     711             : 
     712         440 :   if (fstat (es_fileno (fp), &st))
     713             :     {
     714           0 :       rc = gpg_error_from_syserror ();
     715           0 :       log_error ("can't stat '%s': %s\n", fname, strerror (errno));
     716           0 :       xfree (fname);
     717           0 :       es_fclose (fp);
     718           0 :       return rc;
     719             :     }
     720             : 
     721         440 :   buflen = st.st_size;
     722         440 :   buf = xtrymalloc (buflen+1);
     723         440 :   if (!buf)
     724             :     {
     725           0 :       rc = gpg_error_from_syserror ();
     726           0 :       log_error ("error allocating %zu bytes for '%s': %s\n",
     727           0 :                  buflen, fname, strerror (errno));
     728           0 :       xfree (fname);
     729           0 :       es_fclose (fp);
     730           0 :       xfree (buf);
     731           0 :       return rc;
     732             : 
     733             :     }
     734             : 
     735         440 :   if (es_fread (buf, buflen, 1, fp) != 1)
     736             :     {
     737           0 :       rc = gpg_error_from_syserror ();
     738           0 :       log_error ("error reading %zu bytes from '%s': %s\n",
     739           0 :                  buflen, fname, strerror (errno));
     740           0 :       xfree (fname);
     741           0 :       es_fclose (fp);
     742           0 :       xfree (buf);
     743           0 :       return rc;
     744             :     }
     745             : 
     746             :   /* Convert the file into a gcrypt S-expression object.  */
     747         440 :   rc = gcry_sexp_sscan (&s_skey, &erroff, (char*)buf, buflen);
     748         440 :   xfree (fname);
     749         440 :   es_fclose (fp);
     750         440 :   xfree (buf);
     751         440 :   if (rc)
     752             :     {
     753           0 :       log_error ("failed to build S-Exp (off=%u): %s\n",
     754             :                  (unsigned int)erroff, gpg_strerror (rc));
     755           0 :       return rc;
     756             :     }
     757         440 :   *result = s_skey;
     758         440 :   return 0;
     759             : }
     760             : 
     761             : 
     762             : /* Remove the key identified by GRIP from the private key directory.  */
     763             : static gpg_error_t
     764           0 : remove_key_file (const unsigned char *grip)
     765             : {
     766           0 :   gpg_error_t err = 0;
     767             :   char *fname;
     768             :   char hexgrip[40+4+1];
     769             : 
     770           0 :   bin2hex (grip, 20, hexgrip);
     771           0 :   strcpy (hexgrip+40, ".key");
     772           0 :   fname = make_filename (gnupg_homedir (), GNUPG_PRIVATE_KEYS_DIR,
     773             :                          hexgrip, NULL);
     774           0 :   if (gnupg_remove (fname))
     775           0 :     err = gpg_error_from_syserror ();
     776           0 :   xfree (fname);
     777           0 :   return err;
     778             : }
     779             : 
     780             : 
     781             : /* Return the secret key as an S-Exp in RESULT after locating it using
     782             :    the GRIP.  If the operation shall be diverted to a token, an
     783             :    allocated S-expression with the shadow_info part from the file is
     784             :    stored at SHADOW_INFO; if not NULL will be stored at SHADOW_INFO.
     785             :    CACHE_MODE defines now the cache shall be used.  DESC_TEXT may be
     786             :    set to present a custom description for the pinentry.  LOOKUP_TTL
     787             :    is an optional function to convey a TTL to the cache manager; we do
     788             :    not simply pass the TTL value because the value is only needed if
     789             :    an unprotect action was needed and looking up the TTL may have some
     790             :    overhead (e.g. scanning the sshcontrol file).  If a CACHE_NONCE is
     791             :    given that cache item is first tried to get a passphrase.  If
     792             :    R_PASSPHRASE is not NULL, the function succeeded and the key was
     793             :    protected the used passphrase (entered or from the cache) is stored
     794             :    there; if not NULL will be stored.  The caller needs to free the
     795             :    returned passphrase.   */
     796             : gpg_error_t
     797         400 : agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
     798             :                      const char *desc_text,
     799             :                      const unsigned char *grip, unsigned char **shadow_info,
     800             :                      cache_mode_t cache_mode, lookup_ttl_t lookup_ttl,
     801             :                      gcry_sexp_t *result, char **r_passphrase)
     802             : {
     803             :   int rc;
     804             :   unsigned char *buf;
     805             :   size_t len, buflen, erroff;
     806             :   gcry_sexp_t s_skey;
     807             : 
     808         400 :   *result = NULL;
     809         400 :   if (shadow_info)
     810         400 :     *shadow_info = NULL;
     811         400 :   if (r_passphrase)
     812           2 :     *r_passphrase = NULL;
     813             : 
     814         400 :   rc = read_key_file (grip, &s_skey);
     815         400 :   if (rc)
     816             :     {
     817           0 :       if (gpg_err_code (rc) == GPG_ERR_ENOENT)
     818           0 :         rc = gpg_error (GPG_ERR_NO_SECKEY);
     819           0 :       return rc;
     820             :     }
     821             : 
     822             :   /* For use with the protection functions we also need the key as an
     823             :      canonical encoded S-expression in a buffer.  Create this buffer
     824             :      now.  */
     825         400 :   rc = make_canon_sexp (s_skey, &buf, &len);
     826         400 :   if (rc)
     827           0 :     return rc;
     828             : 
     829         400 :   switch (agent_private_key_type (buf))
     830             :     {
     831             :     case PRIVATE_KEY_CLEAR:
     832         261 :       break; /* no unprotection needed */
     833             :     case PRIVATE_KEY_OPENPGP_NONE:
     834             :       {
     835             :         unsigned char *buf_new;
     836             :         size_t buf_newlen;
     837             : 
     838           2 :         rc = agent_unprotect (ctrl, buf, "", NULL, &buf_new, &buf_newlen);
     839           2 :         if (rc)
     840           0 :           log_error ("failed to convert unprotected openpgp key: %s\n",
     841             :                      gpg_strerror (rc));
     842             :         else
     843             :           {
     844           2 :             xfree (buf);
     845           2 :             buf = buf_new;
     846             :           }
     847             :       }
     848           2 :       break;
     849             :     case PRIVATE_KEY_PROTECTED:
     850             :       {
     851             :         char *desc_text_final;
     852         137 :         char *comment = NULL;
     853             : 
     854             :         /* Note, that we will take the comment as a C string for
     855             :            display purposes; i.e. all stuff beyond a Nul character is
     856             :            ignored.  */
     857             :         {
     858             :           gcry_sexp_t comment_sexp;
     859             : 
     860         137 :           comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
     861         137 :           if (comment_sexp)
     862           0 :             comment = gcry_sexp_nth_string (comment_sexp, 1);
     863         137 :           gcry_sexp_release (comment_sexp);
     864             :         }
     865             : 
     866         137 :         desc_text_final = NULL;
     867         137 :         if (desc_text)
     868         137 :           rc = modify_description (desc_text, comment? comment:"", s_skey,
     869             :                                    &desc_text_final);
     870         137 :         gcry_free (comment);
     871             : 
     872         137 :         if (!rc)
     873             :           {
     874         137 :             rc = unprotect (ctrl, cache_nonce, desc_text_final, &buf, grip,
     875             :                             cache_mode, lookup_ttl, r_passphrase);
     876         137 :             if (rc)
     877           0 :               log_error ("failed to unprotect the secret key: %s\n",
     878             :                          gpg_strerror (rc));
     879             :           }
     880             : 
     881         137 :         xfree (desc_text_final);
     882             :       }
     883         137 :       break;
     884             :     case PRIVATE_KEY_SHADOWED:
     885           0 :       if (shadow_info)
     886             :         {
     887             :           const unsigned char *s;
     888             :           size_t n;
     889             : 
     890           0 :           rc = agent_get_shadow_info (buf, &s);
     891           0 :           if (!rc)
     892             :             {
     893           0 :               n = gcry_sexp_canon_len (s, 0, NULL,NULL);
     894           0 :               assert (n);
     895           0 :               *shadow_info = xtrymalloc (n);
     896           0 :               if (!*shadow_info)
     897           0 :                 rc = out_of_core ();
     898             :               else
     899             :                 {
     900           0 :                   memcpy (*shadow_info, s, n);
     901           0 :                   rc = 0;
     902             :                 }
     903             :             }
     904           0 :           if (rc)
     905           0 :             log_error ("get_shadow_info failed: %s\n", gpg_strerror (rc));
     906             :         }
     907             :       else
     908           0 :         rc = gpg_error (GPG_ERR_UNUSABLE_SECKEY);
     909           0 :       break;
     910             :     default:
     911           0 :       log_error ("invalid private key format\n");
     912           0 :       rc = gpg_error (GPG_ERR_BAD_SECKEY);
     913           0 :       break;
     914             :     }
     915         400 :   gcry_sexp_release (s_skey);
     916         400 :   s_skey = NULL;
     917         400 :   if (rc)
     918             :     {
     919           0 :       xfree (buf);
     920           0 :       if (r_passphrase)
     921             :         {
     922           0 :           xfree (*r_passphrase);
     923           0 :           *r_passphrase = NULL;
     924             :         }
     925           0 :       return rc;
     926             :     }
     927             : 
     928         400 :   buflen = gcry_sexp_canon_len (buf, 0, NULL, NULL);
     929         400 :   rc = gcry_sexp_sscan (&s_skey, &erroff, (char*)buf, buflen);
     930         400 :   wipememory (buf, buflen);
     931         400 :   xfree (buf);
     932         400 :   if (rc)
     933             :     {
     934           0 :       log_error ("failed to build S-Exp (off=%u): %s\n",
     935             :                  (unsigned int)erroff, gpg_strerror (rc));
     936           0 :       if (r_passphrase)
     937             :         {
     938           0 :           xfree (*r_passphrase);
     939           0 :           *r_passphrase = NULL;
     940             :         }
     941           0 :       return rc;
     942             :     }
     943             : 
     944         400 :   *result = s_skey;
     945         400 :   return 0;
     946             : }
     947             : 
     948             : 
     949             : /* Return the string name from the S-expression S_KEY as well as a
     950             :    string describing the names of the parameters.  ALGONAMESIZE and
     951             :    ELEMSSIZE give the allocated size of the provided buffers.  The
     952             :    buffers may be NULL if not required.  If R_LIST is not NULL the top
     953             :    level list will be stored there; the caller needs to release it in
     954             :    this case.  */
     955             : static gpg_error_t
     956         272 : key_parms_from_sexp (gcry_sexp_t s_key, gcry_sexp_t *r_list,
     957             :                      char *r_algoname, size_t algonamesize,
     958             :                      char *r_elems, size_t elemssize)
     959             : {
     960             :   gcry_sexp_t list, l2;
     961             :   const char *name, *algoname, *elems;
     962             :   size_t n;
     963             : 
     964         272 :   if (r_list)
     965         272 :     *r_list = NULL;
     966             : 
     967         272 :   list = gcry_sexp_find_token (s_key, "shadowed-private-key", 0 );
     968         272 :   if (!list)
     969         272 :     list = gcry_sexp_find_token (s_key, "protected-private-key", 0 );
     970         272 :   if (!list)
     971         272 :     list = gcry_sexp_find_token (s_key, "private-key", 0 );
     972         272 :   if (!list)
     973             :     {
     974           0 :       log_error ("invalid private key format\n");
     975           0 :       return gpg_error (GPG_ERR_BAD_SECKEY);
     976             :     }
     977             : 
     978         272 :   l2 = gcry_sexp_cadr (list);
     979         272 :   gcry_sexp_release (list);
     980         272 :   list = l2;
     981         272 :   name = gcry_sexp_nth_data (list, 0, &n);
     982         272 :   if (n==3 && !memcmp (name, "rsa", 3))
     983             :     {
     984          36 :       algoname = "rsa";
     985          36 :       elems = "ne";
     986             :     }
     987         236 :   else if (n==3 && !memcmp (name, "dsa", 3))
     988             :     {
     989         194 :       algoname = "dsa";
     990         194 :       elems = "pqgy";
     991             :     }
     992          42 :   else if (n==3 && !memcmp (name, "ecc", 3))
     993             :     {
     994          42 :       algoname = "ecc";
     995          42 :       elems = "pabgnq";
     996             :     }
     997           0 :   else if (n==5 && !memcmp (name, "ecdsa", 5))
     998             :     {
     999           0 :       algoname = "ecdsa";
    1000           0 :       elems = "pabgnq";
    1001             :     }
    1002           0 :   else if (n==4 && !memcmp (name, "ecdh", 4))
    1003             :     {
    1004           0 :       algoname = "ecdh";
    1005           0 :       elems = "pabgnq";
    1006             :     }
    1007           0 :   else if (n==3 && !memcmp (name, "elg", 3))
    1008             :     {
    1009           0 :       algoname = "elg";
    1010           0 :       elems = "pgy";
    1011             :     }
    1012             :   else
    1013             :     {
    1014           0 :       log_error ("unknown private key algorithm\n");
    1015           0 :       gcry_sexp_release (list);
    1016           0 :       return gpg_error (GPG_ERR_BAD_SECKEY);
    1017             :     }
    1018             : 
    1019         272 :   if (r_algoname)
    1020             :     {
    1021         272 :       if (strlen (algoname) >= algonamesize)
    1022           0 :         return gpg_error (GPG_ERR_BUFFER_TOO_SHORT);
    1023         272 :       strcpy (r_algoname, algoname);
    1024             :     }
    1025         272 :   if (r_elems)
    1026             :     {
    1027           0 :       if (strlen (elems) >= elemssize)
    1028           0 :         return gpg_error (GPG_ERR_BUFFER_TOO_SHORT);
    1029           0 :       strcpy (r_elems, elems);
    1030             :     }
    1031             : 
    1032         272 :   if (r_list)
    1033         272 :     *r_list = list;
    1034             :   else
    1035           0 :     gcry_sexp_release (list);
    1036             : 
    1037         272 :   return 0;
    1038             : }
    1039             : 
    1040             : 
    1041             : /* Return true if KEYPARMS holds an EdDSA key.  */
    1042             : static int
    1043          42 : is_eddsa (gcry_sexp_t keyparms)
    1044             : {
    1045          42 :   int result = 0;
    1046             :   gcry_sexp_t list;
    1047             :   const char *s;
    1048             :   size_t n;
    1049             :   int i;
    1050             : 
    1051          42 :   list = gcry_sexp_find_token (keyparms, "flags", 0);
    1052          42 :   for (i = list ? gcry_sexp_length (list)-1 : 0; i > 0; i--)
    1053             :     {
    1054           0 :       s = gcry_sexp_nth_data (list, i, &n);
    1055           0 :       if (!s)
    1056           0 :         continue; /* Not a data element. */
    1057             : 
    1058           0 :       if (n == 5 && !memcmp (s, "eddsa", 5))
    1059             :         {
    1060           0 :           result = 1;
    1061           0 :           break;
    1062             :         }
    1063             :     }
    1064          42 :   gcry_sexp_release (list);
    1065          42 :   return result;
    1066             : }
    1067             : 
    1068             : 
    1069             : /* Return the public key algorithm number if S_KEY is a DSA style key.
    1070             :    If it is not a DSA style key, return 0.  */
    1071             : int
    1072         136 : agent_is_dsa_key (gcry_sexp_t s_key)
    1073             : {
    1074             :   int result;
    1075             :   gcry_sexp_t list;
    1076             :   char algoname[6];
    1077             : 
    1078         136 :   if (!s_key)
    1079           0 :     return 0;
    1080             : 
    1081         136 :   if (key_parms_from_sexp (s_key, &list, algoname, sizeof algoname, NULL, 0))
    1082           0 :     return 0; /* Error - assume it is not an DSA key.  */
    1083             : 
    1084         136 :   if (!strcmp (algoname, "dsa"))
    1085          97 :     result = GCRY_PK_DSA;
    1086          39 :   else if (!strcmp (algoname, "ecc"))
    1087             :     {
    1088          21 :       if (is_eddsa (list))
    1089           0 :         result = 0;
    1090             :       else
    1091          21 :         result = GCRY_PK_ECDSA;
    1092             :     }
    1093          18 :   else if (!strcmp (algoname, "ecdsa"))
    1094           0 :     result = GCRY_PK_ECDSA;
    1095             :   else
    1096          18 :     result = 0;
    1097             : 
    1098         136 :   gcry_sexp_release (list);
    1099         136 :   return result;
    1100             : }
    1101             : 
    1102             : 
    1103             : /* Return true if S_KEY is an EdDSA key as used with curve Ed25519.  */
    1104             : int
    1105         136 : agent_is_eddsa_key (gcry_sexp_t s_key)
    1106             : {
    1107             :   int result;
    1108             :   gcry_sexp_t list;
    1109             :   char algoname[6];
    1110             : 
    1111         136 :   if (!s_key)
    1112           0 :     return 0;
    1113             : 
    1114         136 :   if (key_parms_from_sexp (s_key, &list, algoname, sizeof algoname, NULL, 0))
    1115           0 :     return 0; /* Error - assume it is not an EdDSA key.  */
    1116             : 
    1117         136 :   if (!strcmp (algoname, "ecc") && is_eddsa (list))
    1118           0 :     result = 1;
    1119         136 :   else if (!strcmp (algoname, "eddsa")) /* backward compatibility.  */
    1120           0 :     result = 1;
    1121             :   else
    1122         136 :     result = 0;
    1123             : 
    1124         136 :   gcry_sexp_release (list);
    1125         136 :   return result;
    1126             : }
    1127             : 
    1128             : 
    1129             : /* Return the key for the keygrip GRIP.  The result is stored at
    1130             :    RESULT.  This function extracts the key from the private key
    1131             :    database and returns it as an S-expression object as it is.  On
    1132             :    failure an error code is returned and NULL stored at RESULT. */
    1133             : gpg_error_t
    1134           0 : agent_raw_key_from_file (ctrl_t ctrl, const unsigned char *grip,
    1135             :                          gcry_sexp_t *result)
    1136             : {
    1137             :   gpg_error_t err;
    1138             :   gcry_sexp_t s_skey;
    1139             : 
    1140             :   (void)ctrl;
    1141             : 
    1142           0 :   *result = NULL;
    1143             : 
    1144           0 :   err = read_key_file (grip, &s_skey);
    1145           0 :   if (!err)
    1146           0 :     *result = s_skey;
    1147           0 :   return err;
    1148             : }
    1149             : 
    1150             : 
    1151             : /* Return the public key for the keygrip GRIP.  The result is stored
    1152             :    at RESULT.  This function extracts the public key from the private
    1153             :    key database.  On failure an error code is returned and NULL stored
    1154             :    at RESULT. */
    1155             : gpg_error_t
    1156          11 : agent_public_key_from_file (ctrl_t ctrl,
    1157             :                             const unsigned char *grip,
    1158             :                             gcry_sexp_t *result)
    1159             : {
    1160             :   gpg_error_t err;
    1161             :   int i, idx;
    1162             :   gcry_sexp_t s_skey;
    1163             :   const char *algoname, *elems;
    1164             :   int npkey;
    1165             :   gcry_mpi_t array[10];
    1166          11 :   gcry_sexp_t curve = NULL;
    1167          11 :   gcry_sexp_t flags = NULL;
    1168             :   gcry_sexp_t uri_sexp, comment_sexp;
    1169             :   const char *uri, *comment;
    1170             :   size_t uri_length, comment_length;
    1171             :   char *format, *p;
    1172             :   void *args[2+7+2+2+1]; /* Size is 2 + max. # of elements + 2 for uri + 2
    1173             :                             for comment + end-of-list.  */
    1174             :   int argidx;
    1175          11 :   gcry_sexp_t list = NULL;
    1176             :   const char *s;
    1177             : 
    1178             :   (void)ctrl;
    1179             : 
    1180          11 :   *result = NULL;
    1181             : 
    1182          11 :   err = read_key_file (grip, &s_skey);
    1183          11 :   if (err)
    1184           0 :     return err;
    1185             : 
    1186         121 :   for (i=0; i < DIM (array); i++)
    1187         110 :     array[i] = NULL;
    1188             : 
    1189          11 :   err = extract_private_key (s_skey, 0, &algoname, &npkey, NULL, &elems,
    1190             :                              array, DIM (array), &curve, &flags);
    1191          11 :   if (err)
    1192             :     {
    1193           0 :       gcry_sexp_release (s_skey);
    1194           0 :       return err;
    1195             :     }
    1196             : 
    1197          11 :   uri = NULL;
    1198          11 :   uri_length = 0;
    1199          11 :   uri_sexp = gcry_sexp_find_token (s_skey, "uri", 0);
    1200          11 :   if (uri_sexp)
    1201           0 :     uri = gcry_sexp_nth_data (uri_sexp, 1, &uri_length);
    1202             : 
    1203          11 :   comment = NULL;
    1204          11 :   comment_length = 0;
    1205          11 :   comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
    1206          11 :   if (comment_sexp)
    1207          11 :     comment = gcry_sexp_nth_data (comment_sexp, 1, &comment_length);
    1208             : 
    1209          11 :   gcry_sexp_release (s_skey);
    1210          11 :   s_skey = NULL;
    1211             : 
    1212             : 
    1213             :   /* FIXME: The following thing is pretty ugly code; we should
    1214             :      investigate how to make it cleaner.  Probably code to handle
    1215             :      canonical S-expressions in a memory buffer is better suited for
    1216             :      such a task.  After all that is what we do in protect.c.  Neeed
    1217             :      to find common patterns and write a straightformward API to use
    1218             :      them.  */
    1219             :   assert (sizeof (size_t) <= sizeof (void*));
    1220             : 
    1221          11 :   format = xtrymalloc (15+4+7*npkey+10+15+1+1);
    1222          11 :   if (!format)
    1223             :     {
    1224           0 :       err = gpg_error_from_syserror ();
    1225           0 :       for (i=0; array[i]; i++)
    1226           0 :         gcry_mpi_release (array[i]);
    1227           0 :       gcry_sexp_release (curve);
    1228           0 :       gcry_sexp_release (flags);
    1229           0 :       gcry_sexp_release (uri_sexp);
    1230           0 :       gcry_sexp_release (comment_sexp);
    1231           0 :       return err;
    1232             :     }
    1233             : 
    1234          11 :   argidx = 0;
    1235          11 :   p = stpcpy (stpcpy (format, "(public-key("), algoname);
    1236          11 :   p = stpcpy (p, "%S%S");       /* curve name and flags.  */
    1237          11 :   args[argidx++] = &curve;
    1238          11 :   args[argidx++] = &flags;
    1239          38 :   for (idx=0, s=elems; idx < npkey; idx++)
    1240             :     {
    1241          27 :       *p++ = '(';
    1242          27 :       *p++ = *s++;
    1243          27 :       p = stpcpy (p, " %m)");
    1244          27 :       assert (argidx < DIM (args));
    1245          27 :       args[argidx++] = &array[idx];
    1246             :     }
    1247          11 :   *p++ = ')';
    1248          11 :   if (uri)
    1249             :     {
    1250           0 :       p = stpcpy (p, "(uri %b)");
    1251           0 :       assert (argidx+1 < DIM (args));
    1252           0 :       args[argidx++] = (void *)&uri_length;
    1253           0 :       args[argidx++] = (void *)&uri;
    1254             :     }
    1255          11 :   if (comment)
    1256             :     {
    1257          11 :       p = stpcpy (p, "(comment %b)");
    1258          11 :       assert (argidx+1 < DIM (args));
    1259          11 :       args[argidx++] = (void *)&comment_length;
    1260          11 :       args[argidx++] = (void*)&comment;
    1261             :     }
    1262          11 :   *p++ = ')';
    1263          11 :   *p = 0;
    1264          11 :   assert (argidx < DIM (args));
    1265          11 :   args[argidx] = NULL;
    1266             : 
    1267          11 :   err = gcry_sexp_build_array (&list, NULL, format, args);
    1268          11 :   xfree (format);
    1269          38 :   for (i=0; array[i]; i++)
    1270          27 :     gcry_mpi_release (array[i]);
    1271          11 :   gcry_sexp_release (curve);
    1272          11 :   gcry_sexp_release (flags);
    1273          11 :   gcry_sexp_release (uri_sexp);
    1274          11 :   gcry_sexp_release (comment_sexp);
    1275             : 
    1276          11 :   if (!err)
    1277          11 :     *result = list;
    1278          11 :   return err;
    1279             : }
    1280             : 
    1281             : 
    1282             : 
    1283             : /* Check whether the the secret key identified by GRIP is available.
    1284             :    Returns 0 is the key is available.  */
    1285             : int
    1286        1022 : agent_key_available (const unsigned char *grip)
    1287             : {
    1288             :   int result;
    1289             :   char *fname;
    1290             :   char hexgrip[40+4+1];
    1291             : 
    1292        1022 :   bin2hex (grip, 20, hexgrip);
    1293        1022 :   strcpy (hexgrip+40, ".key");
    1294             : 
    1295        1022 :   fname = make_filename (gnupg_homedir (), GNUPG_PRIVATE_KEYS_DIR,
    1296             :                          hexgrip, NULL);
    1297        1022 :   result = !access (fname, R_OK)? 0 : -1;
    1298        1022 :   xfree (fname);
    1299        1022 :   return result;
    1300             : }
    1301             : 
    1302             : 
    1303             : 
    1304             : /* Return the information about the secret key specified by the binary
    1305             :    keygrip GRIP.  If the key is a shadowed one the shadow information
    1306             :    will be stored at the address R_SHADOW_INFO as an allocated
    1307             :    S-expression.  */
    1308             : gpg_error_t
    1309          29 : agent_key_info_from_file (ctrl_t ctrl, const unsigned char *grip,
    1310             :                           int *r_keytype, unsigned char **r_shadow_info)
    1311             : {
    1312             :   gpg_error_t err;
    1313             :   unsigned char *buf;
    1314             :   size_t len;
    1315             :   int keytype;
    1316             : 
    1317             :   (void)ctrl;
    1318             : 
    1319          29 :   if (r_keytype)
    1320          29 :     *r_keytype = PRIVATE_KEY_UNKNOWN;
    1321          29 :   if (r_shadow_info)
    1322          29 :     *r_shadow_info = NULL;
    1323             : 
    1324             :   {
    1325             :     gcry_sexp_t sexp;
    1326             : 
    1327          29 :     err = read_key_file (grip, &sexp);
    1328          29 :     if (err)
    1329             :       {
    1330           0 :         if (gpg_err_code (err) == GPG_ERR_ENOENT)
    1331           0 :           return gpg_error (GPG_ERR_NOT_FOUND);
    1332             :         else
    1333           0 :           return err;
    1334             :       }
    1335          29 :     err = make_canon_sexp (sexp, &buf, &len);
    1336          29 :     gcry_sexp_release (sexp);
    1337          29 :     if (err)
    1338           0 :       return err;
    1339             :   }
    1340             : 
    1341          29 :   keytype = agent_private_key_type (buf);
    1342          29 :   switch (keytype)
    1343             :     {
    1344             :     case PRIVATE_KEY_CLEAR:
    1345             :     case PRIVATE_KEY_OPENPGP_NONE:
    1346          17 :       break;
    1347             :     case PRIVATE_KEY_PROTECTED:
    1348             :       /* If we ever require it we could retrieve the comment fields
    1349             :          from such a key. */
    1350          12 :       break;
    1351             :     case PRIVATE_KEY_SHADOWED:
    1352           0 :       if (r_shadow_info)
    1353             :         {
    1354             :           const unsigned char *s;
    1355             :           size_t n;
    1356             : 
    1357           0 :           err = agent_get_shadow_info (buf, &s);
    1358           0 :           if (!err)
    1359             :             {
    1360           0 :               n = gcry_sexp_canon_len (s, 0, NULL, NULL);
    1361           0 :               assert (n);
    1362           0 :               *r_shadow_info = xtrymalloc (n);
    1363           0 :               if (!*r_shadow_info)
    1364           0 :                 err = gpg_error_from_syserror ();
    1365             :               else
    1366           0 :                 memcpy (*r_shadow_info, s, n);
    1367             :             }
    1368             :         }
    1369           0 :       break;
    1370             :     default:
    1371           0 :       err = gpg_error (GPG_ERR_BAD_SECKEY);
    1372           0 :       break;
    1373             :     }
    1374             : 
    1375          29 :   if (!err && r_keytype)
    1376          29 :     *r_keytype = keytype;
    1377             : 
    1378          29 :   xfree (buf);
    1379          29 :   return err;
    1380             : }
    1381             : 
    1382             : 
    1383             : 
    1384             : /* Delete the key with GRIP from the disk after having asked for
    1385             :    confirmation using DESC_TEXT.  If FORCE is set the function won't
    1386             :    require a confirmation via Pinentry or warns if the key is also
    1387             :    used by ssh.
    1388             : 
    1389             :    Common error codes are:
    1390             :      GPG_ERR_NO_SECKEY
    1391             :      GPG_ERR_KEY_ON_CARD
    1392             :      GPG_ERR_NOT_CONFIRMED
    1393             : */
    1394             : gpg_error_t
    1395           0 : agent_delete_key (ctrl_t ctrl, const char *desc_text,
    1396             :                   const unsigned char *grip, int force)
    1397             : {
    1398             :   gpg_error_t err;
    1399           0 :   gcry_sexp_t s_skey = NULL;
    1400           0 :   unsigned char *buf = NULL;
    1401             :   size_t len;
    1402           0 :   char *desc_text_final = NULL;
    1403           0 :   char *comment = NULL;
    1404           0 :   ssh_control_file_t cf = NULL;
    1405             :   char hexgrip[40+4+1];
    1406           0 :   char *default_desc = NULL;
    1407             : 
    1408           0 :   err = read_key_file (grip, &s_skey);
    1409           0 :   if (gpg_err_code (err) == GPG_ERR_ENOENT)
    1410           0 :     err = gpg_error (GPG_ERR_NO_SECKEY);
    1411           0 :   if (err)
    1412           0 :     goto leave;
    1413             : 
    1414           0 :   err = make_canon_sexp (s_skey, &buf, &len);
    1415           0 :   if (err)
    1416           0 :     goto leave;
    1417             : 
    1418           0 :   switch (agent_private_key_type (buf))
    1419             :     {
    1420             :     case PRIVATE_KEY_CLEAR:
    1421             :     case PRIVATE_KEY_OPENPGP_NONE:
    1422             :     case PRIVATE_KEY_PROTECTED:
    1423           0 :       bin2hex (grip, 20, hexgrip);
    1424           0 :       if (!force)
    1425             :         {
    1426           0 :           if (!desc_text)
    1427             :             {
    1428           0 :               default_desc = xtryasprintf
    1429             :           (L_("Do you really want to delete the key identified by keygrip%%0A"
    1430             :               "  %s%%0A  %%C%%0A?"), hexgrip);
    1431           0 :               desc_text = default_desc;
    1432             :             }
    1433             : 
    1434             :           /* Note, that we will take the comment as a C string for
    1435             :              display purposes; i.e. all stuff beyond a Nul character is
    1436             :              ignored.  */
    1437             :           {
    1438             :             gcry_sexp_t comment_sexp;
    1439             : 
    1440           0 :             comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
    1441           0 :             if (comment_sexp)
    1442           0 :               comment = gcry_sexp_nth_string (comment_sexp, 1);
    1443           0 :             gcry_sexp_release (comment_sexp);
    1444             :           }
    1445             : 
    1446           0 :           if (desc_text)
    1447           0 :             err = modify_description (desc_text, comment? comment:"", s_skey,
    1448             :                                       &desc_text_final);
    1449           0 :           if (err)
    1450           0 :             goto leave;
    1451             : 
    1452           0 :           err = agent_get_confirmation (ctrl, desc_text_final,
    1453             :                                         L_("Delete key"), L_("No"), 0);
    1454           0 :           if (err)
    1455           0 :             goto leave;
    1456             : 
    1457           0 :           cf = ssh_open_control_file ();
    1458           0 :           if (cf)
    1459             :             {
    1460           0 :               if (!ssh_search_control_file (cf, hexgrip, NULL, NULL, NULL))
    1461             :                 {
    1462           0 :                   err = agent_get_confirmation
    1463             :                     (ctrl,
    1464             :                      L_("Warning: This key is also listed for use with SSH!\n"
    1465             :                         "Deleting the key might remove your ability to "
    1466             :                         "access remote machines."),
    1467             :                      L_("Delete key"), L_("No"), 0);
    1468           0 :                   if (err)
    1469           0 :                     goto leave;
    1470             :                 }
    1471             :             }
    1472             :         }
    1473           0 :       err = remove_key_file (grip);
    1474           0 :       break;
    1475             : 
    1476             :     case PRIVATE_KEY_SHADOWED:
    1477           0 :       err = remove_key_file (grip);
    1478           0 :       break;
    1479             : 
    1480             :     default:
    1481           0 :       log_error ("invalid private key format\n");
    1482           0 :       err = gpg_error (GPG_ERR_BAD_SECKEY);
    1483           0 :       break;
    1484             :     }
    1485             : 
    1486             :  leave:
    1487           0 :   ssh_close_control_file (cf);
    1488           0 :   gcry_free (comment);
    1489           0 :   xfree (desc_text_final);
    1490           0 :   xfree (default_desc);
    1491           0 :   xfree (buf);
    1492           0 :   gcry_sexp_release (s_skey);
    1493           0 :   return err;
    1494             : }

Generated by: LCOV version 1.11