LCOV - code coverage report
Current view: top level - agent - protect.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 518 855 60.6 %
Date: 2016-11-29 15:00:56 Functions: 15 19 78.9 %

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

Generated by: LCOV version 1.11