LCOV - code coverage report
Current view: top level - agent - findkey.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 320 710 45.1 %
Date: 2016-11-29 15:00:56 Functions: 13 18 72.2 %

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

Generated by: LCOV version 1.11