LCOV - code coverage report
Current view: top level - agent - protect.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 456 794 57.4 %
Date: 2015-11-05 17:10:59 Functions: 14 19 73.7 %

          Line data    Source code
       1             : /* protect.c - Un/Protect a secret key
       2             :  * Copyright (C) 1998-2003, 2007, 2009, 2011 Free Software Foundation, Inc.
       3             :  * Copyright (C) 1998-2003, 2007, 2009, 2011, 2013-2015 Werner Koch
       4             :  *
       5             :  * This file is part of GnuPG.
       6             :  *
       7             :  * GnuPG is free software; you can redistribute it and/or modify
       8             :  * it under the terms of the GNU General Public License as published by
       9             :  * the Free Software Foundation; either version 3 of the License, or
      10             :  * (at your option) any later version.
      11             :  *
      12             :  * GnuPG is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :  * GNU General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License
      18             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      19             :  */
      20             : 
      21             : #include <config.h>
      22             : #include <errno.h>
      23             : #include <stdio.h>
      24             : #include <stdlib.h>
      25             : #include <string.h>
      26             : #include <ctype.h>
      27             : #include <assert.h>
      28             : #include <unistd.h>
      29             : #include <sys/stat.h>
      30             : #ifdef HAVE_W32_SYSTEM
      31             : # ifdef HAVE_WINSOCK2_H
      32             : #  include <winsock2.h>
      33             : # endif
      34             : # include <windows.h>
      35             : #else
      36             : # include <sys/times.h>
      37             : #endif
      38             : 
      39             : #include "agent.h"
      40             : 
      41             : #include "cvt-openpgp.h"
      42             : #include "sexp-parse.h"
      43             : 
      44             : /* The protection mode for encryption.  The supported modes for
      45             :    decryption are listed in agent_unprotect().  */
      46             : #define PROT_CIPHER        GCRY_CIPHER_AES128
      47             : #define PROT_CIPHER_STRING "aes"
      48             : #define PROT_CIPHER_KEYLEN (128/8)
      49             : 
      50             : /* Decode an rfc4880 encoded S2K count.  */
      51             : #define S2K_DECODE_COUNT(_val) ((16ul + ((_val) & 15)) << (((_val) >> 4) + 6))
      52             : 
      53             : 
      54             : /* A table containing the information needed to create a protected
      55             :    private key.  */
      56             : static struct {
      57             :   const char *algo;
      58             :   const char *parmlist;
      59             :   int prot_from, prot_to;
      60             :   int ecc_hack;
      61             : } protect_info[] = {
      62             :   { "rsa",  "nedpqu", 2, 5 },
      63             :   { "dsa",  "pqgyx", 4, 4 },
      64             :   { "elg",  "pgyx", 3, 3 },
      65             :   { "ecdsa","pabgnqd", 6, 6, 1 },
      66             :   { "ecdh", "pabgnqd", 6, 6, 1 },
      67             :   { "ecc",  "pabgnqd", 6, 6, 1 },
      68             :   { NULL }
      69             : };
      70             : 
      71             : 
      72             : /* A helper object for time measurement.  */
      73             : struct calibrate_time_s
      74             : {
      75             : #ifdef HAVE_W32_SYSTEM
      76             :   FILETIME creation_time, exit_time, kernel_time, user_time;
      77             : #else
      78             :   clock_t ticks;
      79             : #endif
      80             : };
      81             : 
      82             : 
      83             : static int
      84             : hash_passphrase (const char *passphrase, int hashalgo,
      85             :                  int s2kmode,
      86             :                  const unsigned char *s2ksalt, unsigned long s2kcount,
      87             :                  unsigned char *key, size_t keylen);
      88             : 
      89             : 
      90             : 
      91             : /* Get the process time and store it in DATA.  */
      92             : static void
      93          40 : calibrate_get_time (struct calibrate_time_s *data)
      94             : {
      95             : #ifdef HAVE_W32_SYSTEM
      96             : # ifdef HAVE_W32CE_SYSTEM
      97             :   GetThreadTimes (GetCurrentThread (),
      98             : # else
      99             :   GetProcessTimes (GetCurrentProcess (),
     100             : # endif
     101             :                    &data->creation_time, &data->exit_time,
     102             :                    &data->kernel_time, &data->user_time);
     103             : #else
     104             :   struct tms tmp;
     105             : 
     106          40 :   times (&tmp);
     107          40 :   data->ticks = tmp.tms_utime;
     108             : #endif
     109          40 : }
     110             : 
     111             : 
     112             : static unsigned long
     113          20 : calibrate_elapsed_time (struct calibrate_time_s *starttime)
     114             : {
     115             :   struct calibrate_time_s stoptime;
     116             : 
     117          20 :   calibrate_get_time (&stoptime);
     118             : #ifdef HAVE_W32_SYSTEM
     119             :   {
     120             :     unsigned long long t1, t2;
     121             : 
     122             :     t1 = (((unsigned long long)starttime->kernel_time.dwHighDateTime << 32)
     123             :           + starttime->kernel_time.dwLowDateTime);
     124             :     t1 += (((unsigned long long)starttime->user_time.dwHighDateTime << 32)
     125             :            + starttime->user_time.dwLowDateTime);
     126             :     t2 = (((unsigned long long)stoptime.kernel_time.dwHighDateTime << 32)
     127             :           + stoptime.kernel_time.dwLowDateTime);
     128             :     t2 += (((unsigned long long)stoptime.user_time.dwHighDateTime << 32)
     129             :            + stoptime.user_time.dwLowDateTime);
     130             :     return (unsigned long)((t2 - t1)/10000);
     131             :   }
     132             : #else
     133          40 :   return (unsigned long)((((double) (stoptime.ticks - starttime->ticks))
     134          20 :                           /CLOCKS_PER_SEC)*10000000);
     135             : #endif
     136             : }
     137             : 
     138             : 
     139             : /* Run a test hashing for COUNT and return the time required in
     140             :    milliseconds.  */
     141             : static unsigned long
     142          20 : calibrate_s2k_count_one (unsigned long count)
     143             : {
     144             :   int rc;
     145             :   char keybuf[PROT_CIPHER_KEYLEN];
     146             :   struct calibrate_time_s starttime;
     147             : 
     148          20 :   calibrate_get_time (&starttime);
     149          20 :   rc = hash_passphrase ("123456789abcdef0", GCRY_MD_SHA1,
     150             :                         3, "saltsalt", count, keybuf, sizeof keybuf);
     151          20 :   if (rc)
     152           0 :     BUG ();
     153          20 :   return calibrate_elapsed_time (&starttime);
     154             : }
     155             : 
     156             : 
     157             : /* Measure the time we need to do the hash operations and deduce an
     158             :    S2K count which requires about 100ms of time.  */
     159             : static unsigned long
     160           2 : calibrate_s2k_count (void)
     161             : {
     162             :   unsigned long count;
     163             :   unsigned long ms;
     164             : 
     165          20 :   for (count = 65536; count; count *= 2)
     166             :     {
     167          20 :       ms = calibrate_s2k_count_one (count);
     168          20 :       if (opt.verbose > 1)
     169           0 :         log_info ("S2K calibration: %lu -> %lums\n", count, ms);
     170          20 :       if (ms > 100)
     171           2 :         break;
     172             :     }
     173             : 
     174           2 :   count = (unsigned long)(((double)count / ms) * 100);
     175           2 :   count /= 1024;
     176           2 :   count *= 1024;
     177           2 :   if (count < 65536)
     178           0 :     count = 65536;
     179             : 
     180           2 :   if (opt.verbose)
     181             :     {
     182           0 :       ms = calibrate_s2k_count_one (count);
     183           0 :       log_info ("S2K calibration: %lu -> %lums\n", count, ms);
     184             :     }
     185             : 
     186           2 :   return count;
     187             : }
     188             : 
     189             : 
     190             : 
     191             : /* Return the standard S2K count.  */
     192             : unsigned long
     193          16 : get_standard_s2k_count (void)
     194             : {
     195             :   static unsigned long count;
     196             : 
     197          16 :   if (!count)
     198           2 :     count = calibrate_s2k_count ();
     199             : 
     200             :   /* Enforce a lower limit.  */
     201          16 :   return count < 65536 ? 65536 : count;
     202             : }
     203             : 
     204             : 
     205             : /* Same as get_standard_s2k_count but return the count in the encoding
     206             :    as described by rfc4880.  */
     207             : unsigned char
     208           0 : get_standard_s2k_count_rfc4880 (void)
     209             : {
     210             :   unsigned long iterations;
     211             :   unsigned int count;
     212             :   unsigned char result;
     213           0 :   unsigned char c=0;
     214             : 
     215           0 :   iterations = get_standard_s2k_count ();
     216           0 :   if (iterations >= 65011712)
     217           0 :     return 255;
     218             : 
     219             :   /* Need count to be in the range 16-31 */
     220           0 :   for (count=iterations>>6; count>=32; count>>=1)
     221           0 :     c++;
     222             : 
     223           0 :   result = (c<<4)|(count-16);
     224             : 
     225           0 :   if (S2K_DECODE_COUNT(result) < iterations)
     226           0 :     result++;
     227             : 
     228           0 :   return result;
     229             : 
     230             : }
     231             : 
     232             : 
     233             : 
     234             : /* Calculate the MIC for a private key or shared secret S-expression.
     235             :    SHA1HASH should point to a 20 byte buffer.  This function is
     236             :    suitable for all algorithms. */
     237             : static int
     238         114 : calculate_mic (const unsigned char *plainkey, unsigned char *sha1hash)
     239             : {
     240             :   const unsigned char *hash_begin, *hash_end;
     241             :   const unsigned char *s;
     242             :   size_t n;
     243             :   int is_shared_secret;
     244             : 
     245         114 :   s = plainkey;
     246         114 :   if (*s != '(')
     247           0 :     return gpg_error (GPG_ERR_INV_SEXP);
     248         114 :   s++;
     249         114 :   n = snext (&s);
     250         114 :   if (!n)
     251           0 :     return gpg_error (GPG_ERR_INV_SEXP);
     252         114 :   if (smatch (&s, n, "private-key"))
     253         114 :     is_shared_secret = 0;
     254           0 :   else if (smatch (&s, n, "shared-secret"))
     255           0 :     is_shared_secret = 1;
     256             :   else
     257           0 :     return gpg_error (GPG_ERR_UNKNOWN_SEXP);
     258         114 :   if (*s != '(')
     259           0 :     return gpg_error (GPG_ERR_UNKNOWN_SEXP);
     260         114 :   hash_begin = s;
     261         114 :   if (!is_shared_secret)
     262             :     {
     263         114 :       s++;
     264         114 :       n = snext (&s);
     265         114 :       if (!n)
     266           0 :         return gpg_error (GPG_ERR_INV_SEXP);
     267         114 :       s += n; /* Skip the algorithm name.  */
     268             :     }
     269             : 
     270         829 :   while (*s == '(')
     271             :     {
     272         601 :       s++;
     273         601 :       n = snext (&s);
     274         601 :       if (!n)
     275           0 :         return gpg_error (GPG_ERR_INV_SEXP);
     276         601 :       s += n;
     277         601 :       n = snext (&s);
     278         601 :       if (!n)
     279           0 :         return gpg_error (GPG_ERR_INV_SEXP);
     280         601 :       s += n;
     281         601 :       if ( *s != ')' )
     282           0 :         return gpg_error (GPG_ERR_INV_SEXP);
     283         601 :       s++;
     284             :     }
     285         114 :   if (*s != ')')
     286           0 :     return gpg_error (GPG_ERR_INV_SEXP);
     287         114 :   s++;
     288         114 :   hash_end = s;
     289             : 
     290         114 :   gcry_md_hash_buffer (GCRY_MD_SHA1, sha1hash,
     291         114 :                        hash_begin, hash_end - hash_begin);
     292             : 
     293         114 :   return 0;
     294             : }
     295             : 
     296             : 
     297             : 
     298             : /* Encrypt the parameter block starting at PROTBEGIN with length
     299             :    PROTLEN using the utf8 encoded key PASSPHRASE and return the entire
     300             :    encrypted block in RESULT or return with an error code.  SHA1HASH
     301             :    is the 20 byte SHA-1 hash required for the integrity code.
     302             : 
     303             :    The parameter block is expected to be an incomplete S-Expression of
     304             :    the form (example in advanced format):
     305             : 
     306             :      (d #046129F..[some bytes not shown]..81#)
     307             :      (p #00e861b..[some bytes not shown]..f1#)
     308             :      (q #00f7a7c..[some bytes not shown]..61#)
     309             :      (u #304559a..[some bytes not shown]..9b#)
     310             : 
     311             :    the returned block is the S-Expression:
     312             : 
     313             :     (protected mode (parms) encrypted_octet_string)
     314             : 
     315             : */
     316             : static int
     317           8 : do_encryption (const unsigned char *protbegin, size_t protlen,
     318             :                const char *passphrase,  const unsigned char *sha1hash,
     319             :                unsigned char **result, size_t *resultlen,
     320             :                unsigned long s2k_count)
     321             : {
     322             :   gcry_cipher_hd_t hd;
     323           8 :   const char *modestr = "openpgp-s2k3-sha1-" PROT_CIPHER_STRING "-cbc";
     324             :   int blklen, enclen, outlen;
     325           8 :   unsigned char *iv = NULL;
     326             :   int rc;
     327           8 :   char *outbuf = NULL;
     328             :   char *p;
     329             :   int saltpos, ivpos, encpos;
     330             : 
     331           8 :   *resultlen = 0;
     332           8 :   *result = NULL;
     333             : 
     334           8 :   rc = gcry_cipher_open (&hd, PROT_CIPHER, GCRY_CIPHER_MODE_CBC,
     335             :                          GCRY_CIPHER_SECURE);
     336           8 :   if (rc)
     337           0 :     return rc;
     338             : 
     339             : 
     340             :   /* We need to work on a copy of the data because this makes it
     341             :      easier to add the trailer and the padding and more important we
     342             :      have to prefix the text with 2 parenthesis, so we have to
     343             :      allocate enough space for:
     344             : 
     345             :      ((<parameter_list>)(4:hash4:sha120:<hashvalue>)) + padding
     346             : 
     347             :      We always append a full block of random bytes as padding but
     348             :      encrypt only what is needed for a full blocksize.  */
     349           8 :   blklen = gcry_cipher_get_algo_blklen (PROT_CIPHER);
     350           8 :   outlen = 2 + protlen + 2 + 6 + 6 + 23 + 2 + blklen;
     351           8 :   enclen = outlen/blklen * blklen;
     352           8 :   outbuf = gcry_malloc_secure (outlen);
     353           8 :   if (!outbuf)
     354           0 :     rc = out_of_core ();
     355           8 :   if (!rc)
     356             :     {
     357             :       /* Allocate random bytes to be used as IV, padding and s2k salt. */
     358           8 :       iv = xtrymalloc (blklen*2+8);
     359           8 :       if (!iv)
     360           0 :         rc = gpg_error (GPG_ERR_ENOMEM);
     361             :       else
     362             :         {
     363           8 :           gcry_create_nonce (iv, blklen*2+8);
     364           8 :           rc = gcry_cipher_setiv (hd, iv, blklen);
     365             :         }
     366             :     }
     367           8 :   if (!rc)
     368             :     {
     369             :       unsigned char *key;
     370           8 :       size_t keylen = PROT_CIPHER_KEYLEN;
     371             : 
     372           8 :       key = gcry_malloc_secure (keylen);
     373           8 :       if (!key)
     374           0 :         rc = out_of_core ();
     375             :       else
     376             :         {
     377          16 :           rc = hash_passphrase (passphrase, GCRY_MD_SHA1,
     378           8 :                                 3, iv+2*blklen,
     379             :                                 s2k_count ? s2k_count : get_standard_s2k_count(),
     380             :                                 key, keylen);
     381           8 :           if (!rc)
     382           8 :             rc = gcry_cipher_setkey (hd, key, keylen);
     383           8 :           xfree (key);
     384             :         }
     385             :     }
     386           8 :   if (!rc)
     387             :     {
     388           8 :       p = outbuf;
     389           8 :       *p++ = '(';
     390           8 :       *p++ = '(';
     391           8 :       memcpy (p, protbegin, protlen);
     392           8 :       p += protlen;
     393           8 :       memcpy (p, ")(4:hash4:sha120:", 17);
     394           8 :       p += 17;
     395           8 :       memcpy (p, sha1hash, 20);
     396           8 :       p += 20;
     397           8 :       *p++ = ')';
     398           8 :       *p++ = ')';
     399           8 :       memcpy (p, iv+blklen, blklen);
     400           8 :       p += blklen;
     401           8 :       assert ( p - outbuf == outlen);
     402           8 :       rc = gcry_cipher_encrypt (hd, outbuf, enclen, NULL, 0);
     403             :     }
     404           8 :   gcry_cipher_close (hd);
     405           8 :   if (rc)
     406             :     {
     407           0 :       xfree (iv);
     408           0 :       xfree (outbuf);
     409           0 :       return rc;
     410             :     }
     411             : 
     412             :   /* Now allocate the buffer we want to return.  This is
     413             : 
     414             :      (protected openpgp-s2k3-sha1-aes-cbc
     415             :        ((sha1 salt no_of_iterations) 16byte_iv)
     416             :        encrypted_octet_string)
     417             : 
     418             :      in canoncical format of course.  We use asprintf and %n modifier
     419             :      and dummy values as placeholders.  */
     420             :   {
     421             :     char countbuf[35];
     422             : 
     423           8 :     snprintf (countbuf, sizeof countbuf, "%lu",
     424             :             s2k_count ? s2k_count : get_standard_s2k_count ());
     425          16 :     p = xtryasprintf
     426             :       ("(9:protected%d:%s((4:sha18:%n_8bytes_%u:%s)%d:%n%*s)%d:%n%*s)",
     427           8 :        (int)strlen (modestr), modestr,
     428             :        &saltpos,
     429           8 :        (unsigned int)strlen (countbuf), countbuf,
     430             :        blklen, &ivpos, blklen, "",
     431             :        enclen, &encpos, enclen, "");
     432           8 :     if (!p)
     433             :       {
     434           0 :         gpg_error_t tmperr = out_of_core ();
     435           0 :         xfree (iv);
     436           0 :         xfree (outbuf);
     437           0 :         return tmperr;
     438             :       }
     439             :   }
     440           8 :   *resultlen = strlen (p);
     441           8 :   *result = (unsigned char*)p;
     442           8 :   memcpy (p+saltpos, iv+2*blklen, 8);
     443           8 :   memcpy (p+ivpos, iv, blklen);
     444           8 :   memcpy (p+encpos, outbuf, enclen);
     445           8 :   xfree (iv);
     446           8 :   xfree (outbuf);
     447           8 :   return 0;
     448             : }
     449             : 
     450             : 
     451             : 
     452             : /* Protect the key encoded in canonical format in PLAINKEY.  We assume
     453             :    a valid S-Exp here. */
     454             : int
     455          11 : agent_protect (const unsigned char *plainkey, const char *passphrase,
     456             :                unsigned char **result, size_t *resultlen,
     457             :                unsigned long s2k_count)
     458             : {
     459             :   int rc;
     460             :   const char *parmlist;
     461             :   int prot_from_idx, prot_to_idx;
     462             :   const unsigned char *s;
     463             :   const unsigned char *hash_begin, *hash_end;
     464             :   const unsigned char *prot_begin, *prot_end, *real_end;
     465             :   size_t n;
     466             :   int c, infidx, i;
     467             :   unsigned char hashvalue[20];
     468             :   char timestamp_exp[35];
     469             :   unsigned char *protected;
     470             :   size_t protectedlen;
     471          11 :   int depth = 0;
     472             :   unsigned char *p;
     473             :   gcry_md_hd_t md;
     474          11 :   int have_curve = 0;
     475             : 
     476             :   /* Create an S-expression with the protected-at timestamp.  */
     477          11 :   memcpy (timestamp_exp, "(12:protected-at15:", 19);
     478          11 :   gnupg_get_isotime (timestamp_exp+19);
     479          11 :   timestamp_exp[19+15] = ')';
     480             : 
     481             :   /* Parse original key.  */
     482          11 :   s = plainkey;
     483          11 :   if (*s != '(')
     484           1 :     return gpg_error (GPG_ERR_INV_SEXP);
     485          10 :   depth++;
     486          10 :   s++;
     487          10 :   n = snext (&s);
     488          10 :   if (!n)
     489           0 :     return gpg_error (GPG_ERR_INV_SEXP);
     490          10 :   if (!smatch (&s, n, "private-key"))
     491           0 :     return gpg_error (GPG_ERR_UNKNOWN_SEXP);
     492          10 :   if (*s != '(')
     493           0 :     return gpg_error (GPG_ERR_UNKNOWN_SEXP);
     494          10 :   depth++;
     495          10 :   hash_begin = s;
     496          10 :   s++;
     497          10 :   n = snext (&s);
     498          10 :   if (!n)
     499           0 :     return gpg_error (GPG_ERR_INV_SEXP);
     500             : 
     501          53 :   for (infidx=0; protect_info[infidx].algo
     502          76 :               && !smatch (&s, n, protect_info[infidx].algo); infidx++)
     503             :     ;
     504          10 :   if (!protect_info[infidx].algo)
     505           0 :     return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
     506             : 
     507             :   /* The parser below is a complete mess: To make it robust for ECC
     508             :      use we should reorder the s-expression to include only what we
     509             :      really need and thus guarantee the right order for saving stuff.
     510             :      This should be done before calling this function and maybe with
     511             :      the help of the new gcry_sexp_extract_param.  */
     512          10 :   parmlist      = protect_info[infidx].parmlist;
     513          10 :   prot_from_idx = protect_info[infidx].prot_from;
     514          10 :   prot_to_idx   = protect_info[infidx].prot_to;
     515          10 :   prot_begin = prot_end = NULL;
     516          44 :   for (i=0; (c=parmlist[i]); i++)
     517             :     {
     518          35 :       if (i == prot_from_idx)
     519           9 :         prot_begin = s;
     520          35 :       if (*s != '(')
     521           0 :         return gpg_error (GPG_ERR_INV_SEXP);
     522          35 :       depth++;
     523          35 :       s++;
     524          35 :       n = snext (&s);
     525          35 :       if (!n)
     526           0 :         return gpg_error (GPG_ERR_INV_SEXP);
     527          35 :       if (n != 1 || c != *s)
     528             :         {
     529           8 :           if (n == 5 && !memcmp (s, "curve", 5)
     530           7 :               && !i && protect_info[infidx].ecc_hack)
     531             :             {
     532             :               /* This is a private ECC key but the first parameter is
     533             :                  the name of the curve.  We change the parameter list
     534             :                  here to the one we expect in this case.  */
     535           7 :               have_curve = 1;
     536           7 :               parmlist = "?qd";
     537           7 :               prot_from_idx = 2;
     538           7 :               prot_to_idx = 2;
     539             :             }
     540           1 :           else if (n == 5 && !memcmp (s, "flags", 5)
     541           0 :                    && i == 1 && have_curve)
     542             :             {
     543             :               /* "curve" followed by "flags": Change again.  */
     544           0 :               parmlist = "??qd";
     545           0 :               prot_from_idx = 3;
     546           0 :               prot_to_idx = 3;
     547             :             }
     548             :           else
     549           1 :             return gpg_error (GPG_ERR_INV_SEXP);
     550             :         }
     551          34 :       s += n;
     552          34 :       n = snext (&s);
     553          34 :       if (!n)
     554           0 :         return gpg_error (GPG_ERR_INV_SEXP);
     555          34 :       s +=n; /* skip value */
     556          34 :       if (*s != ')')
     557           0 :         return gpg_error (GPG_ERR_INV_SEXP);
     558          34 :       depth--;
     559          34 :       if (i == prot_to_idx)
     560           9 :         prot_end = s;
     561          34 :       s++;
     562             :     }
     563           9 :   if (*s != ')' || !prot_begin || !prot_end )
     564           0 :     return gpg_error (GPG_ERR_INV_SEXP);
     565           9 :   depth--;
     566           9 :   hash_end = s;
     567           9 :   s++;
     568             :   /* Skip to the end of the S-expression.  */
     569           9 :   assert (depth == 1);
     570           9 :   rc = sskip (&s, &depth);
     571           9 :   if (rc)
     572           1 :     return rc;
     573           8 :   assert (!depth);
     574           8 :   real_end = s-1;
     575             : 
     576             :   /* Hash the stuff.  Because the timestamp_exp won't get protected,
     577             :      we can't simply hash a continuous buffer but need to use several
     578             :      md_writes.  */
     579           8 :   rc = gcry_md_open (&md, GCRY_MD_SHA1, 0 );
     580           8 :   if (rc)
     581           0 :     return rc;
     582           8 :   gcry_md_write (md, hash_begin, hash_end - hash_begin);
     583           8 :   gcry_md_write (md, timestamp_exp, 35);
     584           8 :   gcry_md_write (md, ")", 1);
     585           8 :   memcpy (hashvalue, gcry_md_read (md, GCRY_MD_SHA1), 20);
     586           8 :   gcry_md_close (md);
     587             : 
     588           8 :   rc = do_encryption (prot_begin, prot_end - prot_begin + 1,
     589             :                       passphrase,  hashvalue,
     590             :                       &protected, &protectedlen, s2k_count);
     591           8 :   if (rc)
     592           0 :     return rc;
     593             : 
     594             :   /* Now create the protected version of the key.  Note that the 10
     595             :      extra bytes are for for the inserted "protected-" string (the
     596             :      beginning of the plaintext reads: "((11:private-key(" ).  The 35
     597             :      term is the space for (12:protected-at15:<timestamp>).  */
     598           8 :   *resultlen = (10
     599           8 :                 + (prot_begin-plainkey)
     600           8 :                 + protectedlen
     601             :                 + 35
     602           8 :                 + (real_end-prot_end));
     603           8 :   *result = p = xtrymalloc (*resultlen);
     604           8 :   if (!p)
     605             :     {
     606           0 :       gpg_error_t tmperr = out_of_core ();
     607           0 :       xfree (protected);
     608           0 :       return tmperr;
     609             :     }
     610           8 :   memcpy (p, "(21:protected-", 14);
     611           8 :   p += 14;
     612           8 :   memcpy (p, plainkey+4, prot_begin - plainkey - 4);
     613           8 :   p += prot_begin - plainkey - 4;
     614           8 :   memcpy (p, protected, protectedlen);
     615           8 :   p += protectedlen;
     616             : 
     617           8 :   memcpy (p, timestamp_exp, 35);
     618           8 :   p += 35;
     619             : 
     620           8 :   memcpy (p, prot_end+1, real_end - prot_end);
     621           8 :   p += real_end - prot_end;
     622           8 :   assert ( p - *result == *resultlen);
     623           8 :   xfree (protected);
     624             : 
     625           8 :   return 0;
     626             : }
     627             : 
     628             : 
     629             : 
     630             : /* Do the actual decryption and check the return list for consistency.  */
     631             : static int
     632         114 : do_decryption (const unsigned char *protected, size_t protectedlen,
     633             :                const char *passphrase,
     634             :                const unsigned char *s2ksalt, unsigned long s2kcount,
     635             :                const unsigned char *iv, size_t ivlen,
     636             :                int prot_cipher, int prot_cipher_keylen,
     637             :                unsigned char **result)
     638             : {
     639         114 :   int rc = 0;
     640             :   int blklen;
     641             :   gcry_cipher_hd_t hd;
     642             :   unsigned char *outbuf;
     643             :   size_t reallen;
     644             : 
     645         114 :   blklen = gcry_cipher_get_algo_blklen (prot_cipher);
     646         114 :   if (protectedlen < 4 || (protectedlen%blklen))
     647           0 :     return gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
     648             : 
     649         114 :   rc = gcry_cipher_open (&hd, prot_cipher, GCRY_CIPHER_MODE_CBC,
     650             :                          GCRY_CIPHER_SECURE);
     651         114 :   if (rc)
     652           0 :     return rc;
     653             : 
     654         114 :   outbuf = gcry_malloc_secure (protectedlen);
     655         114 :   if (!outbuf)
     656           0 :     rc = out_of_core ();
     657         114 :   if (!rc)
     658         114 :     rc = gcry_cipher_setiv (hd, iv, ivlen);
     659         114 :   if (!rc)
     660             :     {
     661             :       unsigned char *key;
     662             : 
     663         114 :       key = gcry_malloc_secure (prot_cipher_keylen);
     664         114 :       if (!key)
     665           0 :         rc = out_of_core ();
     666             :       else
     667             :         {
     668         114 :           rc = hash_passphrase (passphrase, GCRY_MD_SHA1,
     669             :                                 3, s2ksalt, s2kcount, key, prot_cipher_keylen);
     670         114 :           if (!rc)
     671         114 :             rc = gcry_cipher_setkey (hd, key, prot_cipher_keylen);
     672         114 :           xfree (key);
     673             :         }
     674             :     }
     675         114 :   if (!rc)
     676         114 :     rc = gcry_cipher_decrypt (hd, outbuf, protectedlen,
     677             :                               protected, protectedlen);
     678         114 :   gcry_cipher_close (hd);
     679         114 :   if (rc)
     680             :     {
     681           0 :       xfree (outbuf);
     682           0 :       return rc;
     683             :     }
     684             :   /* Do a quick check first. */
     685         114 :   if (*outbuf != '(' && outbuf[1] != '(')
     686             :     {
     687           0 :       xfree (outbuf);
     688           0 :       return gpg_error (GPG_ERR_BAD_PASSPHRASE);
     689             :     }
     690             :   /* Check that we have a consistent S-Exp. */
     691         114 :   reallen = gcry_sexp_canon_len (outbuf, protectedlen, NULL, NULL);
     692         114 :   if (!reallen || (reallen + blklen < protectedlen) )
     693             :     {
     694           0 :       xfree (outbuf);
     695           0 :       return gpg_error (GPG_ERR_BAD_PASSPHRASE);
     696             :     }
     697         114 :   *result = outbuf;
     698         114 :   return 0;
     699             : }
     700             : 
     701             : 
     702             : /* Merge the parameter list contained in CLEARTEXT with the original
     703             :    protect lists PROTECTEDKEY by replacing the list at REPLACEPOS.
     704             :    Return the new list in RESULT and the MIC value in the 20 byte
     705             :    buffer SHA1HASH.  CUTOFF and CUTLEN will receive the offset and the
     706             :    length of the resulting list which should go into the MIC
     707             :    calculation but then be removed.  */
     708             : static int
     709         114 : merge_lists (const unsigned char *protectedkey,
     710             :              size_t replacepos,
     711             :              const unsigned char *cleartext,
     712             :              unsigned char *sha1hash,
     713             :              unsigned char **result, size_t *resultlen,
     714             :              size_t *cutoff, size_t *cutlen)
     715             : {
     716             :   size_t n, newlistlen;
     717             :   unsigned char *newlist, *p;
     718             :   const unsigned char *s;
     719             :   const unsigned char *startpos, *endpos;
     720             :   int i, rc;
     721             : 
     722         114 :   *result = NULL;
     723         114 :   *resultlen = 0;
     724         114 :   *cutoff = 0;
     725         114 :   *cutlen = 0;
     726             : 
     727         114 :   if (replacepos < 26)
     728           0 :     return gpg_error (GPG_ERR_BUG);
     729             : 
     730             :   /* Estimate the required size of the resulting list.  We have a large
     731             :      safety margin of >20 bytes (MIC hash from CLEARTEXT and the
     732             :      removed "protected-" */
     733         114 :   newlistlen = gcry_sexp_canon_len (protectedkey, 0, NULL, NULL);
     734         114 :   if (!newlistlen)
     735           0 :     return gpg_error (GPG_ERR_BUG);
     736         114 :   n = gcry_sexp_canon_len (cleartext, 0, NULL, NULL);
     737         114 :   if (!n)
     738           0 :     return gpg_error (GPG_ERR_BUG);
     739         114 :   newlistlen += n;
     740         114 :   newlist = gcry_malloc_secure (newlistlen);
     741         114 :   if (!newlist)
     742           0 :     return out_of_core ();
     743             : 
     744             :   /* Copy the initial segment */
     745         114 :   strcpy ((char*)newlist, "(11:private-key");
     746         114 :   p = newlist + 15;
     747         114 :   memcpy (p, protectedkey+15+10, replacepos-15-10);
     748         114 :   p += replacepos-15-10;
     749             : 
     750             :   /* copy the cleartext */
     751         114 :   s = cleartext;
     752         114 :   if (*s != '(' && s[1] != '(')
     753           0 :     return gpg_error (GPG_ERR_BUG);  /*we already checked this */
     754         114 :   s += 2;
     755         114 :   startpos = s;
     756         342 :   while ( *s == '(' )
     757             :     {
     758         114 :       s++;
     759         114 :       n = snext (&s);
     760         114 :       if (!n)
     761           0 :         goto invalid_sexp;
     762         114 :       s += n;
     763         114 :       n = snext (&s);
     764         114 :       if (!n)
     765           0 :         goto invalid_sexp;
     766         114 :       s += n;
     767         114 :       if ( *s != ')' )
     768           0 :         goto invalid_sexp;
     769         114 :       s++;
     770             :     }
     771         114 :   if ( *s != ')' )
     772           0 :     goto invalid_sexp;
     773         114 :   endpos = s;
     774         114 :   s++;
     775             :   /* Intermezzo: Get the MIC */
     776         114 :   if (*s != '(')
     777           0 :     goto invalid_sexp;
     778         114 :   s++;
     779         114 :   n = snext (&s);
     780         114 :   if (!smatch (&s, n, "hash"))
     781           0 :     goto invalid_sexp;
     782         114 :   n = snext (&s);
     783         114 :   if (!smatch (&s, n, "sha1"))
     784           0 :     goto invalid_sexp;
     785         114 :   n = snext (&s);
     786         114 :   if (n != 20)
     787           0 :     goto invalid_sexp;
     788         114 :   memcpy (sha1hash, s, 20);
     789         114 :   s += n;
     790         114 :   if (*s != ')')
     791           0 :     goto invalid_sexp;
     792             :   /* End intermezzo */
     793             : 
     794             :   /* append the parameter list */
     795         114 :   memcpy (p, startpos, endpos - startpos);
     796         114 :   p += endpos - startpos;
     797             : 
     798             :   /* Skip over the protected list element in the original list.  */
     799         114 :   s = protectedkey + replacepos;
     800         114 :   assert (*s == '(');
     801         114 :   s++;
     802         114 :   i = 1;
     803         114 :   rc = sskip (&s, &i);
     804         114 :   if (rc)
     805           0 :     goto failure;
     806             :   /* Record the position of the optional protected-at expression.  */
     807         114 :   if (*s == '(')
     808             :     {
     809         114 :       const unsigned char *save_s = s;
     810         114 :       s++;
     811         114 :       n = snext (&s);
     812         114 :       if (smatch (&s, n, "protected-at"))
     813             :         {
     814         114 :           i = 1;
     815         114 :           rc = sskip (&s, &i);
     816         114 :           if (rc)
     817           0 :             goto failure;
     818         114 :           *cutlen = s - save_s;
     819             :         }
     820         114 :       s = save_s;
     821             :     }
     822         114 :   startpos = s;
     823         114 :   i = 2; /* we are inside this level */
     824         114 :   rc = sskip (&s, &i);
     825         114 :   if (rc)
     826           0 :     goto failure;
     827         114 :   assert (s[-1] == ')');
     828         114 :   endpos = s; /* one behind the end of the list */
     829             : 
     830             :   /* Append the rest. */
     831         114 :   if (*cutlen)
     832         114 :     *cutoff = p - newlist;
     833         114 :   memcpy (p, startpos, endpos - startpos);
     834         114 :   p += endpos - startpos;
     835             : 
     836             : 
     837             :   /* ready */
     838         114 :   *result = newlist;
     839         114 :   *resultlen = newlistlen;
     840         114 :   return 0;
     841             : 
     842             :  failure:
     843           0 :   wipememory (newlist, newlistlen);
     844           0 :   xfree (newlist);
     845           0 :   return rc;
     846             : 
     847             :  invalid_sexp:
     848           0 :   wipememory (newlist, newlistlen);
     849           0 :   xfree (newlist);
     850           0 :   return gpg_error (GPG_ERR_INV_SEXP);
     851             : }
     852             : 
     853             : 
     854             : 
     855             : /* Unprotect the key encoded in canonical format.  We assume a valid
     856             :    S-Exp here.  If a protected-at item is available, its value will
     857             :    be stored at protected_at unless this is NULL.  */
     858             : int
     859         120 : agent_unprotect (ctrl_t ctrl,
     860             :                  const unsigned char *protectedkey, const char *passphrase,
     861             :                  gnupg_isotime_t protected_at,
     862             :                  unsigned char **result, size_t *resultlen)
     863             : {
     864             :   static struct {
     865             :     const char *name; /* Name of the protection method. */
     866             :     int algo;         /* (A zero indicates the "openpgp-native" hack.)  */
     867             :     int keylen;       /* Used key length in bytes.  */
     868             :   } algotable[] = {
     869             :     { "openpgp-s2k3-sha1-aes-cbc",    GCRY_CIPHER_AES128, (128/8)},
     870             :     { "openpgp-s2k3-sha1-aes256-cbc", GCRY_CIPHER_AES256, (256/8)},
     871             :     { "openpgp-native", 0, 0 }
     872             :   };
     873             :   int rc;
     874             :   const unsigned char *s;
     875             :   const unsigned char *protect_list;
     876             :   size_t n;
     877             :   int infidx, i;
     878             :   unsigned char sha1hash[20], sha1hash2[20];
     879             :   const unsigned char *s2ksalt;
     880             :   unsigned long s2kcount;
     881             :   const unsigned char *iv;
     882             :   int prot_cipher, prot_cipher_keylen;
     883             :   const unsigned char *prot_begin;
     884             :   unsigned char *cleartext;
     885             :   unsigned char *final;
     886             :   size_t finallen;
     887             :   size_t cutoff, cutlen;
     888             : 
     889         120 :   if (protected_at)
     890           0 :     *protected_at = 0;
     891             : 
     892         120 :   s = protectedkey;
     893         120 :   if (*s != '(')
     894           0 :     return gpg_error (GPG_ERR_INV_SEXP);
     895         120 :   s++;
     896         120 :   n = snext (&s);
     897         120 :   if (!n)
     898           0 :     return gpg_error (GPG_ERR_INV_SEXP);
     899         120 :   if (!smatch (&s, n, "protected-private-key"))
     900           0 :     return gpg_error (GPG_ERR_UNKNOWN_SEXP);
     901         120 :   if (*s != '(')
     902           0 :     return gpg_error (GPG_ERR_UNKNOWN_SEXP);
     903         120 :   s++;
     904         120 :   n = snext (&s);
     905         120 :   if (!n)
     906           0 :     return gpg_error (GPG_ERR_INV_SEXP);
     907             : 
     908         545 :   for (infidx=0; protect_info[infidx].algo
     909         730 :               && !smatch (&s, n, protect_info[infidx].algo); infidx++)
     910             :     ;
     911         120 :   if (!protect_info[infidx].algo)
     912           0 :     return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
     913             : 
     914             : 
     915             :   /* See wether we have a protected-at timestamp.  */
     916         120 :   protect_list = s;  /* Save for later.  */
     917         120 :   if (protected_at)
     918             :     {
     919           0 :       while (*s == '(')
     920             :         {
     921           0 :           prot_begin = s;
     922           0 :           s++;
     923           0 :           n = snext (&s);
     924           0 :           if (!n)
     925           0 :             return gpg_error (GPG_ERR_INV_SEXP);
     926           0 :           if (smatch (&s, n, "protected-at"))
     927             :             {
     928           0 :               n = snext (&s);
     929           0 :               if (!n)
     930           0 :                 return gpg_error (GPG_ERR_INV_SEXP);
     931           0 :               if (n != 15)
     932           0 :                 return gpg_error (GPG_ERR_UNKNOWN_SEXP);
     933           0 :               memcpy (protected_at, s, 15);
     934           0 :               protected_at[15] = 0;
     935           0 :               break;
     936             :             }
     937           0 :           s += n;
     938           0 :           i = 1;
     939           0 :           rc = sskip (&s, &i);
     940           0 :           if (rc)
     941           0 :             return rc;
     942             :         }
     943             :     }
     944             : 
     945             :   /* Now find the list with the protected information.  Here is an
     946             :      example for such a list:
     947             :      (protected openpgp-s2k3-sha1-aes-cbc
     948             :         ((sha1 <salt> <count>) <Initialization_Vector>)
     949             :         <encrypted_data>)
     950             :    */
     951         120 :   s = protect_list;
     952             :   for (;;)
     953             :     {
     954         505 :       if (*s != '(')
     955           0 :         return gpg_error (GPG_ERR_INV_SEXP);
     956         505 :       prot_begin = s;
     957         505 :       s++;
     958         505 :       n = snext (&s);
     959         505 :       if (!n)
     960           0 :         return gpg_error (GPG_ERR_INV_SEXP);
     961         505 :       if (smatch (&s, n, "protected"))
     962         120 :         break;
     963         385 :       s += n;
     964         385 :       i = 1;
     965         385 :       rc = sskip (&s, &i);
     966         385 :       if (rc)
     967           0 :         return rc;
     968         385 :     }
     969             :   /* found */
     970         120 :   n = snext (&s);
     971         120 :   if (!n)
     972           0 :     return gpg_error (GPG_ERR_INV_SEXP);
     973             : 
     974             :   /* Lookup the protection algo.  */
     975         120 :   prot_cipher = 0;        /* (avoid gcc warning) */
     976         120 :   prot_cipher_keylen = 0; /* (avoid gcc warning) */
     977         132 :   for (i= 0; i < DIM (algotable); i++)
     978         132 :     if (smatch (&s, n, algotable[i].name))
     979             :       {
     980         120 :         prot_cipher = algotable[i].algo;
     981         120 :         prot_cipher_keylen = algotable[i].keylen;
     982         120 :         break;
     983             :       }
     984         120 :   if (i == DIM (algotable))
     985           0 :     return gpg_error (GPG_ERR_UNSUPPORTED_PROTECTION);
     986             : 
     987         120 :   if (!prot_cipher)  /* This is "openpgp-native".  */
     988             :     {
     989             :       gcry_sexp_t s_prot_begin;
     990             : 
     991           6 :       rc = gcry_sexp_sscan (&s_prot_begin, NULL,
     992             :                             prot_begin,
     993             :                             gcry_sexp_canon_len (prot_begin, 0,NULL,NULL));
     994           6 :       if (rc)
     995           0 :         return rc;
     996             : 
     997           6 :       rc = convert_from_openpgp_native (ctrl, s_prot_begin, passphrase, &final);
     998           6 :       gcry_sexp_release (s_prot_begin);
     999           6 :       if (!rc)
    1000             :         {
    1001           6 :           *result = final;
    1002           6 :           *resultlen = gcry_sexp_canon_len (final, 0, NULL, NULL);
    1003             :         }
    1004           6 :       return rc;
    1005             :     }
    1006             : 
    1007         114 :   if (*s != '(' || s[1] != '(')
    1008           0 :     return gpg_error (GPG_ERR_INV_SEXP);
    1009         114 :   s += 2;
    1010         114 :   n = snext (&s);
    1011         114 :   if (!n)
    1012           0 :     return gpg_error (GPG_ERR_INV_SEXP);
    1013         114 :   if (!smatch (&s, n, "sha1"))
    1014           0 :     return gpg_error (GPG_ERR_UNSUPPORTED_PROTECTION);
    1015         114 :   n = snext (&s);
    1016         114 :   if (n != 8)
    1017           0 :     return gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
    1018         114 :   s2ksalt = s;
    1019         114 :   s += n;
    1020         114 :   n = snext (&s);
    1021         114 :   if (!n)
    1022           0 :     return gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
    1023             :   /* We expect a list close as next, so we can simply use strtoul()
    1024             :      here.  We might want to check that we only have digits - but this
    1025             :      is nothing we should worry about */
    1026         114 :   if (s[n] != ')' )
    1027           0 :     return gpg_error (GPG_ERR_INV_SEXP);
    1028             : 
    1029             :   /* Old versions of gpg-agent used the funny floating point number in
    1030             :      a byte encoding as specified by OpenPGP.  However this is not
    1031             :      needed and thus we now store it as a plain unsigned integer.  We
    1032             :      can easily distinguish the old format by looking at its value:
    1033             :      Less than 256 is an old-style encoded number; other values are
    1034             :      plain integers.  In any case we check that they are at least
    1035             :      65536 because we never used a lower value in the past and we
    1036             :      should have a lower limit.  */
    1037         114 :   s2kcount = strtoul ((const char*)s, NULL, 10);
    1038         114 :   if (!s2kcount)
    1039           0 :     return gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
    1040         114 :   if (s2kcount < 256)
    1041           0 :     s2kcount = (16ul + (s2kcount & 15)) << ((s2kcount >> 4) + 6);
    1042         114 :   if (s2kcount < 65536)
    1043           0 :     return gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
    1044             : 
    1045         114 :   s += n;
    1046         114 :   s++; /* skip list end */
    1047             : 
    1048         114 :   n = snext (&s);
    1049         114 :   if (n != 16) /* Wrong blocksize for IV (we support only 128 bit). */
    1050           0 :     return gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
    1051         114 :   iv = s;
    1052         114 :   s += n;
    1053         114 :   if (*s != ')' )
    1054           0 :     return gpg_error (GPG_ERR_INV_SEXP);
    1055         114 :   s++;
    1056         114 :   n = snext (&s);
    1057         114 :   if (!n)
    1058           0 :     return gpg_error (GPG_ERR_INV_SEXP);
    1059             : 
    1060         114 :   cleartext = NULL; /* Avoid cc warning. */
    1061         114 :   rc = do_decryption (s, n,
    1062             :                       passphrase, s2ksalt, s2kcount,
    1063             :                       iv, 16, prot_cipher, prot_cipher_keylen,
    1064             :                       &cleartext);
    1065         114 :   if (rc)
    1066           0 :     return rc;
    1067             : 
    1068         114 :   rc = merge_lists (protectedkey, prot_begin-protectedkey, cleartext,
    1069             :                     sha1hash, &final, &finallen, &cutoff, &cutlen);
    1070             :   /* Albeit cleartext has been allocated in secure memory and thus
    1071             :      xfree will wipe it out, we do an extra wipe just in case
    1072             :      somethings goes badly wrong. */
    1073         114 :   wipememory (cleartext, n);
    1074         114 :   xfree (cleartext);
    1075         114 :   if (rc)
    1076           0 :     return rc;
    1077             : 
    1078         114 :   rc = calculate_mic (final, sha1hash2);
    1079         114 :   if (!rc && memcmp (sha1hash, sha1hash2, 20))
    1080           0 :     rc = gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
    1081         114 :   if (rc)
    1082             :     {
    1083           0 :       wipememory (final, finallen);
    1084           0 :       xfree (final);
    1085           0 :       return rc;
    1086             :     }
    1087             :   /* Now remove the part which is included in the MIC but should not
    1088             :      go into the final thing.  */
    1089         114 :   if (cutlen)
    1090             :     {
    1091         114 :       memmove (final+cutoff, final+cutoff+cutlen, finallen-cutoff-cutlen);
    1092         114 :       finallen -= cutlen;
    1093             :     }
    1094             : 
    1095         114 :   *result = final;
    1096         114 :   *resultlen = gcry_sexp_canon_len (final, 0, NULL, NULL);
    1097         114 :   return 0;
    1098             : }
    1099             : 
    1100             : /* Check the type of the private key, this is one of the constants:
    1101             :    PRIVATE_KEY_UNKNOWN if we can't figure out the type (this is the
    1102             :    value 0), PRIVATE_KEY_CLEAR for an unprotected private key.
    1103             :    PRIVATE_KEY_PROTECTED for an protected private key or
    1104             :    PRIVATE_KEY_SHADOWED for a sub key where the secret parts are
    1105             :    stored elsewhere.  Finally PRIVATE_KEY_OPENPGP_NONE may be returned
    1106             :    is the key is still in the openpgp-native format but without
    1107             :    protection.  */
    1108             : int
    1109         372 : agent_private_key_type (const unsigned char *privatekey)
    1110             : {
    1111             :   const unsigned char *s;
    1112             :   size_t n;
    1113             :   int i;
    1114             : 
    1115         372 :   s = privatekey;
    1116         372 :   if (*s != '(')
    1117           0 :     return PRIVATE_KEY_UNKNOWN;
    1118         372 :   s++;
    1119         372 :   n = snext (&s);
    1120         372 :   if (!n)
    1121           0 :     return PRIVATE_KEY_UNKNOWN;
    1122         372 :   if (smatch (&s, n, "protected-private-key"))
    1123             :     {
    1124             :       /* We need to check whether this is openpgp-native protected
    1125             :          with the protection method "none".  In that case we return a
    1126             :          different key type so that the caller knows that there is no
    1127             :          need to ask for a passphrase. */
    1128         120 :       if (*s != '(')
    1129           0 :         return PRIVATE_KEY_PROTECTED; /* Unknown sexp - assume protected. */
    1130         120 :       s++;
    1131         120 :       n = snext (&s);
    1132         120 :       if (!n)
    1133           0 :         return PRIVATE_KEY_UNKNOWN; /* Invalid sexp.  */
    1134         120 :       s += n; /* Skip over the algo */
    1135             : 
    1136             :       /* Find the (protected ...) list.  */
    1137             :       for (;;)
    1138             :         {
    1139         505 :           if (*s != '(')
    1140           0 :             return PRIVATE_KEY_UNKNOWN; /* Invalid sexp.  */
    1141         505 :           s++;
    1142         505 :           n = snext (&s);
    1143         505 :           if (!n)
    1144           0 :             return PRIVATE_KEY_UNKNOWN; /* Invalid sexp.  */
    1145         505 :           if (smatch (&s, n, "protected"))
    1146         120 :             break;
    1147         385 :           s += n;
    1148         385 :           i = 1;
    1149         385 :           if (sskip (&s, &i))
    1150           0 :             return PRIVATE_KEY_UNKNOWN; /* Invalid sexp.  */
    1151         385 :         }
    1152             :       /* Found - Is this openpgp-native? */
    1153         120 :       n = snext (&s);
    1154         120 :       if (!n)
    1155           0 :         return PRIVATE_KEY_UNKNOWN; /* Invalid sexp.  */
    1156         120 :       if (smatch (&s, n, "openpgp-native")) /* Yes.  */
    1157             :         {
    1158           6 :           if (*s != '(')
    1159           0 :             return PRIVATE_KEY_UNKNOWN; /* Unknown sexp. */
    1160           6 :           s++;
    1161           6 :           n = snext (&s);
    1162           6 :           if (!n)
    1163           0 :             return PRIVATE_KEY_UNKNOWN; /* Invalid sexp.  */
    1164           6 :           s += n; /* Skip over "openpgp-private-key".  */
    1165             :           /* Find the (protection ...) list.  */
    1166             :           for (;;)
    1167             :             {
    1168          36 :               if (*s != '(')
    1169           0 :                 return PRIVATE_KEY_UNKNOWN; /* Invalid sexp.  */
    1170          36 :               s++;
    1171          36 :               n = snext (&s);
    1172          36 :               if (!n)
    1173           0 :                 return PRIVATE_KEY_UNKNOWN; /* Invalid sexp.  */
    1174          36 :               if (smatch (&s, n, "protection"))
    1175           6 :                 break;
    1176          30 :               s += n;
    1177          30 :               i = 1;
    1178          30 :               if (sskip (&s, &i))
    1179           0 :                 return PRIVATE_KEY_UNKNOWN; /* Invalid sexp.  */
    1180          30 :             }
    1181             :           /* Found - Is the mode "none"? */
    1182           6 :           n = snext (&s);
    1183           6 :           if (!n)
    1184           0 :             return PRIVATE_KEY_UNKNOWN; /* Invalid sexp.  */
    1185           6 :           log_debug ("openpgp-native protection '%.*s'\n", (int)n, s);
    1186           6 :           if (smatch (&s, n, "none"))
    1187           0 :             return PRIVATE_KEY_OPENPGP_NONE;  /* Yes.  */
    1188             :         }
    1189             : 
    1190         120 :       return PRIVATE_KEY_PROTECTED;
    1191             :     }
    1192         252 :   if (smatch (&s, n, "shadowed-private-key"))
    1193           0 :     return PRIVATE_KEY_SHADOWED;
    1194         252 :   if (smatch (&s, n, "private-key"))
    1195         252 :     return PRIVATE_KEY_CLEAR;
    1196           0 :   return PRIVATE_KEY_UNKNOWN;
    1197             : }
    1198             : 
    1199             : 
    1200             : 
    1201             : /* Transform a passphrase into a suitable key of length KEYLEN and
    1202             :    store this key in the caller provided buffer KEY.  The caller must
    1203             :    provide an HASHALGO, a valid S2KMODE (see rfc-2440) and depending on
    1204             :    that mode an S2KSALT of 8 random bytes and an S2KCOUNT.
    1205             : 
    1206             :    Returns an error code on failure.  */
    1207             : static int
    1208         148 : hash_passphrase (const char *passphrase, int hashalgo,
    1209             :                  int s2kmode,
    1210             :                  const unsigned char *s2ksalt,
    1211             :                  unsigned long s2kcount,
    1212             :                  unsigned char *key, size_t keylen)
    1213             : {
    1214             :   /* The key derive function does not support a zero length string for
    1215             :      the passphrase in the S2K modes.  Return a better suited error
    1216             :      code than GPG_ERR_INV_DATA.  */
    1217         148 :   if (!passphrase || !*passphrase)
    1218           0 :     return gpg_error (GPG_ERR_NO_PASSPHRASE);
    1219         148 :   return gcry_kdf_derive (passphrase, strlen (passphrase),
    1220             :                           s2kmode == 3? GCRY_KDF_ITERSALTED_S2K :
    1221           0 :                           s2kmode == 1? GCRY_KDF_SALTED_S2K :
    1222           0 :                           s2kmode == 0? GCRY_KDF_SIMPLE_S2K : GCRY_KDF_NONE,
    1223             :                           hashalgo, s2ksalt, 8, s2kcount,
    1224             :                           keylen, key);
    1225             : }
    1226             : 
    1227             : 
    1228             : gpg_error_t
    1229           6 : s2k_hash_passphrase (const char *passphrase, int hashalgo,
    1230             :                      int s2kmode,
    1231             :                      const unsigned char *s2ksalt,
    1232             :                      unsigned int s2kcount,
    1233             :                      unsigned char *key, size_t keylen)
    1234             : {
    1235           6 :   return hash_passphrase (passphrase, hashalgo, s2kmode, s2ksalt,
    1236           6 :                           S2K_DECODE_COUNT (s2kcount),
    1237             :                           key, keylen);
    1238             : }
    1239             : 
    1240             : 
    1241             : 
    1242             : 
    1243             : /* Create an canonical encoded S-expression with the shadow info from
    1244             :    a card's SERIALNO and the IDSTRING.  */
    1245             : unsigned char *
    1246           0 : make_shadow_info (const char *serialno, const char *idstring)
    1247             : {
    1248             :   const char *s;
    1249             :   char *info, *p;
    1250             :   char numbuf[20];
    1251             :   size_t n;
    1252             : 
    1253           0 :   for (s=serialno, n=0; *s && s[1]; s += 2)
    1254           0 :     n++;
    1255             : 
    1256           0 :   info = p = xtrymalloc (1 + sizeof numbuf + n
    1257             :                            + sizeof numbuf + strlen (idstring) + 1 + 1);
    1258           0 :   if (!info)
    1259           0 :     return NULL;
    1260           0 :   *p++ = '(';
    1261           0 :   p = stpcpy (p, smklen (numbuf, sizeof numbuf, n, NULL));
    1262           0 :   for (s=serialno; *s && s[1]; s += 2)
    1263           0 :     *(unsigned char *)p++ = xtoi_2 (s);
    1264           0 :   p = stpcpy (p, smklen (numbuf, sizeof numbuf, strlen (idstring), NULL));
    1265           0 :   p = stpcpy (p, idstring);
    1266           0 :   *p++ = ')';
    1267           0 :   *p = 0;
    1268           0 :   return (unsigned char *)info;
    1269             : }
    1270             : 
    1271             : 
    1272             : 
    1273             : /* Create a shadow key from a public key.  We use the shadow protocol
    1274             :   "ti-v1" and insert the S-expressionn SHADOW_INFO.  The resulting
    1275             :   S-expression is returned in an allocated buffer RESULT will point
    1276             :   to. The input parameters are expected to be valid canonicalized
    1277             :   S-expressions */
    1278             : int
    1279           0 : agent_shadow_key (const unsigned char *pubkey,
    1280             :                   const unsigned char *shadow_info,
    1281             :                   unsigned char **result)
    1282             : {
    1283             :   const unsigned char *s;
    1284             :   const unsigned char *point;
    1285             :   size_t n;
    1286           0 :   int depth = 0;
    1287             :   char *p;
    1288           0 :   size_t pubkey_len = gcry_sexp_canon_len (pubkey, 0, NULL,NULL);
    1289           0 :   size_t shadow_info_len = gcry_sexp_canon_len (shadow_info, 0, NULL,NULL);
    1290             : 
    1291           0 :   if (!pubkey_len || !shadow_info_len)
    1292           0 :     return gpg_error (GPG_ERR_INV_VALUE);
    1293           0 :   s = pubkey;
    1294           0 :   if (*s != '(')
    1295           0 :     return gpg_error (GPG_ERR_INV_SEXP);
    1296           0 :   depth++;
    1297           0 :   s++;
    1298           0 :   n = snext (&s);
    1299           0 :   if (!n)
    1300           0 :     return gpg_error (GPG_ERR_INV_SEXP);
    1301           0 :   if (!smatch (&s, n, "public-key"))
    1302           0 :     return gpg_error (GPG_ERR_UNKNOWN_SEXP);
    1303           0 :   if (*s != '(')
    1304           0 :     return gpg_error (GPG_ERR_UNKNOWN_SEXP);
    1305           0 :   depth++;
    1306           0 :   s++;
    1307           0 :   n = snext (&s);
    1308           0 :   if (!n)
    1309           0 :     return gpg_error (GPG_ERR_INV_SEXP);
    1310           0 :   s += n; /* skip over the algorithm name */
    1311             : 
    1312           0 :   while (*s != ')')
    1313             :     {
    1314           0 :       if (*s != '(')
    1315           0 :         return gpg_error (GPG_ERR_INV_SEXP);
    1316           0 :       depth++;
    1317           0 :       s++;
    1318           0 :       n = snext (&s);
    1319           0 :       if (!n)
    1320           0 :         return gpg_error (GPG_ERR_INV_SEXP);
    1321           0 :       s += n;
    1322           0 :       n = snext (&s);
    1323           0 :       if (!n)
    1324           0 :         return gpg_error (GPG_ERR_INV_SEXP);
    1325           0 :       s +=n; /* skip value */
    1326           0 :       if (*s != ')')
    1327           0 :         return gpg_error (GPG_ERR_INV_SEXP);
    1328           0 :       depth--;
    1329           0 :       s++;
    1330             :     }
    1331           0 :   point = s; /* insert right before the point */
    1332           0 :   depth--;
    1333           0 :   s++;
    1334           0 :   assert (depth == 1);
    1335             : 
    1336             :   /* Calculate required length by taking in account: the "shadowed-"
    1337             :      prefix, the "shadowed", "t1-v1" as well as some parenthesis */
    1338           0 :   n = 12 + pubkey_len + 1 + 3+8 + 2+5 + shadow_info_len + 1;
    1339           0 :   *result = xtrymalloc (n);
    1340           0 :   p = (char*)*result;
    1341           0 :   if (!p)
    1342           0 :       return out_of_core ();
    1343           0 :   p = stpcpy (p, "(20:shadowed-private-key");
    1344             :   /* (10:public-key ...)*/
    1345           0 :   memcpy (p, pubkey+14, point - (pubkey+14));
    1346           0 :   p += point - (pubkey+14);
    1347           0 :   p = stpcpy (p, "(8:shadowed5:t1-v1");
    1348           0 :   memcpy (p, shadow_info, shadow_info_len);
    1349           0 :   p += shadow_info_len;
    1350           0 :   *p++ = ')';
    1351           0 :   memcpy (p, point, pubkey_len - (point - pubkey));
    1352           0 :   p += pubkey_len - (point - pubkey);
    1353             : 
    1354           0 :   return 0;
    1355             : }
    1356             : 
    1357             : /* Parse a canonical encoded shadowed key and return a pointer to the
    1358             :    inner list with the shadow_info */
    1359             : int
    1360           0 : agent_get_shadow_info (const unsigned char *shadowkey,
    1361             :                        unsigned char const **shadow_info)
    1362             : {
    1363             :   const unsigned char *s;
    1364             :   size_t n;
    1365           0 :   int depth = 0;
    1366             : 
    1367           0 :   s = shadowkey;
    1368           0 :   if (*s != '(')
    1369           0 :     return gpg_error (GPG_ERR_INV_SEXP);
    1370           0 :   depth++;
    1371           0 :   s++;
    1372           0 :   n = snext (&s);
    1373           0 :   if (!n)
    1374           0 :     return gpg_error (GPG_ERR_INV_SEXP);
    1375           0 :   if (!smatch (&s, n, "shadowed-private-key"))
    1376           0 :     return gpg_error (GPG_ERR_UNKNOWN_SEXP);
    1377           0 :   if (*s != '(')
    1378           0 :     return gpg_error (GPG_ERR_UNKNOWN_SEXP);
    1379           0 :   depth++;
    1380           0 :   s++;
    1381           0 :   n = snext (&s);
    1382           0 :   if (!n)
    1383           0 :     return gpg_error (GPG_ERR_INV_SEXP);
    1384           0 :   s += n; /* skip over the algorithm name */
    1385             : 
    1386             :   for (;;)
    1387             :     {
    1388           0 :       if (*s == ')')
    1389           0 :         return gpg_error (GPG_ERR_UNKNOWN_SEXP);
    1390           0 :       if (*s != '(')
    1391           0 :         return gpg_error (GPG_ERR_INV_SEXP);
    1392           0 :       depth++;
    1393           0 :       s++;
    1394           0 :       n = snext (&s);
    1395           0 :       if (!n)
    1396           0 :         return gpg_error (GPG_ERR_INV_SEXP);
    1397           0 :       if (smatch (&s, n, "shadowed"))
    1398           0 :         break;
    1399           0 :       s += n;
    1400           0 :       n = snext (&s);
    1401           0 :       if (!n)
    1402           0 :         return gpg_error (GPG_ERR_INV_SEXP);
    1403           0 :       s +=n; /* skip value */
    1404           0 :       if (*s != ')')
    1405           0 :         return gpg_error (GPG_ERR_INV_SEXP);
    1406           0 :       depth--;
    1407           0 :       s++;
    1408           0 :     }
    1409             :   /* Found the shadowed list, S points to the protocol */
    1410           0 :   n = snext (&s);
    1411           0 :   if (!n)
    1412           0 :     return gpg_error (GPG_ERR_INV_SEXP);
    1413           0 :   if (smatch (&s, n, "t1-v1"))
    1414             :     {
    1415           0 :       if (*s != '(')
    1416           0 :         return gpg_error (GPG_ERR_INV_SEXP);
    1417           0 :       *shadow_info = s;
    1418             :     }
    1419             :   else
    1420           0 :     return gpg_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
    1421           0 :   return 0;
    1422             : }
    1423             : 
    1424             : 
    1425             : /* Parse the canonical encoded SHADOW_INFO S-expression.  On success
    1426             :    the hex encoded serial number is returned as a malloced strings at
    1427             :    R_HEXSN and the Id string as a malloced string at R_IDSTR.  On
    1428             :    error an error code is returned and NULL is stored at the result
    1429             :    parameters addresses.  If the serial number or the ID string is not
    1430             :    required, NULL may be passed for them.  */
    1431             : gpg_error_t
    1432           0 : parse_shadow_info (const unsigned char *shadow_info,
    1433             :                    char **r_hexsn, char **r_idstr, int *r_pinlen)
    1434             : {
    1435             :   const unsigned char *s;
    1436             :   size_t n;
    1437             : 
    1438           0 :   if (r_hexsn)
    1439           0 :     *r_hexsn = NULL;
    1440           0 :   if (r_idstr)
    1441           0 :     *r_idstr = NULL;
    1442           0 :   if (r_pinlen)
    1443           0 :     *r_pinlen = 0;
    1444             : 
    1445           0 :   s = shadow_info;
    1446           0 :   if (*s != '(')
    1447           0 :     return gpg_error (GPG_ERR_INV_SEXP);
    1448           0 :   s++;
    1449           0 :   n = snext (&s);
    1450           0 :   if (!n)
    1451           0 :     return gpg_error (GPG_ERR_INV_SEXP);
    1452             : 
    1453           0 :   if (r_hexsn)
    1454             :     {
    1455           0 :       *r_hexsn = bin2hex (s, n, NULL);
    1456           0 :       if (!*r_hexsn)
    1457           0 :         return gpg_error_from_syserror ();
    1458             :     }
    1459           0 :   s += n;
    1460             : 
    1461           0 :   n = snext (&s);
    1462           0 :   if (!n)
    1463             :     {
    1464           0 :       if (r_hexsn)
    1465             :         {
    1466           0 :           xfree (*r_hexsn);
    1467           0 :           *r_hexsn = NULL;
    1468             :         }
    1469           0 :       return gpg_error (GPG_ERR_INV_SEXP);
    1470             :     }
    1471             : 
    1472           0 :   if (r_idstr)
    1473             :     {
    1474           0 :       *r_idstr = xtrymalloc (n+1);
    1475           0 :       if (!*r_idstr)
    1476             :         {
    1477           0 :           if (r_hexsn)
    1478             :             {
    1479           0 :               xfree (*r_hexsn);
    1480           0 :               *r_hexsn = NULL;
    1481             :             }
    1482           0 :           return gpg_error_from_syserror ();
    1483             :         }
    1484           0 :       memcpy (*r_idstr, s, n);
    1485           0 :       (*r_idstr)[n] = 0;
    1486             :     }
    1487             : 
    1488             :   /* Parse the optional PINLEN.  */
    1489           0 :   n = snext (&s);
    1490           0 :   if (!n)
    1491           0 :     return 0;
    1492             : 
    1493           0 :   if (r_pinlen)
    1494             :     {
    1495           0 :       char *tmpstr = xtrymalloc (n+1);
    1496           0 :       if (!tmpstr)
    1497             :         {
    1498           0 :           if (r_hexsn)
    1499             :             {
    1500           0 :               xfree (*r_hexsn);
    1501           0 :               *r_hexsn = NULL;
    1502             :             }
    1503           0 :           if (r_idstr)
    1504             :             {
    1505           0 :               xfree (*r_idstr);
    1506           0 :               *r_idstr = NULL;
    1507             :             }
    1508           0 :           return gpg_error_from_syserror ();
    1509             :         }
    1510           0 :       memcpy (tmpstr, s, n);
    1511           0 :       tmpstr[n] = 0;
    1512             : 
    1513           0 :       *r_pinlen = (int)strtol (tmpstr, NULL, 10);
    1514           0 :       xfree (tmpstr);
    1515             :     }
    1516             : 
    1517           0 :   return 0;
    1518             : }

Generated by: LCOV version 1.11