LCOV - code coverage report
Current view: top level - agent - cvt-openpgp.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 479 644 74.4 %
Date: 2016-09-12 13:01:59 Functions: 15 15 100.0 %

          Line data    Source code
       1             : /* cvt-openpgp.c - Convert an OpenPGP key to our internal format.
       2             :  * Copyright (C) 1998-2002, 2006, 2009, 2010 Free Software Foundation, Inc.
       3             :  * Copyright (C) 2013, 2014 Werner Koch
       4             :  *
       5             :  * This file is part of GnuPG.
       6             :  *
       7             :  * GnuPG is free software; you can redistribute it and/or modify
       8             :  * it under the terms of the GNU General Public License as published by
       9             :  * the Free Software Foundation; either version 3 of the License, or
      10             :  * (at your option) any later version.
      11             :  *
      12             :  * GnuPG is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :  * GNU General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License
      18             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      19             :  */
      20             : 
      21             : #include <config.h>
      22             : #include <stdio.h>
      23             : #include <stdlib.h>
      24             : #include <string.h>
      25             : #include <assert.h>
      26             : 
      27             : #include "agent.h"
      28             : #include "i18n.h"
      29             : #include "cvt-openpgp.h"
      30             : #include "host2net.h"
      31             : 
      32             : 
      33             : /* Helper to pass data via the callback to do_unprotect. */
      34             : struct try_do_unprotect_arg_s
      35             : {
      36             :   int  is_v4;
      37             :   int  is_protected;
      38             :   int  pubkey_algo;
      39             :   const char *curve;
      40             :   int  protect_algo;
      41             :   char *iv;
      42             :   int  ivlen;
      43             :   int  s2k_mode;
      44             :   int  s2k_algo;
      45             :   byte *s2k_salt;
      46             :   u32  s2k_count;
      47             :   u16 desired_csum;
      48             :   gcry_mpi_t *skey;
      49             :   size_t skeysize;
      50             :   int skeyidx;
      51             :   gcry_sexp_t *r_key;
      52             : };
      53             : 
      54             : 
      55             : 
      56             : /* Compute the keygrip from the public key and store it at GRIP.  */
      57             : static gpg_error_t
      58          29 : get_keygrip (int pubkey_algo, const char *curve, gcry_mpi_t *pkey,
      59             :              unsigned char *grip)
      60             : {
      61             :   gpg_error_t err;
      62          29 :   gcry_sexp_t s_pkey = NULL;
      63             : 
      64          29 :   switch (pubkey_algo)
      65             :     {
      66             :     case GCRY_PK_DSA:
      67           9 :       err = gcry_sexp_build (&s_pkey, NULL,
      68             :                              "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))",
      69           9 :                              pkey[0], pkey[1], pkey[2], pkey[3]);
      70           3 :       break;
      71             : 
      72             :     case GCRY_PK_ELG:
      73           6 :       err = gcry_sexp_build (&s_pkey, NULL,
      74             :                              "(public-key(elg(p%m)(g%m)(y%m)))",
      75           6 :                              pkey[0], pkey[1], pkey[2]);
      76           3 :       break;
      77             : 
      78             :     case GCRY_PK_RSA:
      79           5 :       err = gcry_sexp_build (&s_pkey, NULL,
      80           5 :                              "(public-key(rsa(n%m)(e%m)))", pkey[0], pkey[1]);
      81           5 :       break;
      82             : 
      83             :     case GCRY_PK_ECC:
      84          18 :       if (!curve)
      85           0 :         err = gpg_error (GPG_ERR_BAD_SECKEY);
      86             :       else
      87             :         {
      88             :           const char *format;
      89             : 
      90          18 :           if (!strcmp (curve, "Ed25519"))
      91           0 :             format = "(public-key(ecc(curve %s)(flags eddsa)(q%m)))";
      92          18 :           else if (!strcmp (curve, "Curve25519"))
      93           0 :             format = "(public-key(ecc(curve %s)(flags djb-tweak)(q%m)))";
      94             :           else
      95          18 :             format = "(public-key(ecc(curve %s)(q%m)))";
      96             : 
      97          18 :           err = gcry_sexp_build (&s_pkey, NULL, format, curve, pkey[0]);
      98             :         }
      99          18 :       break;
     100             : 
     101             :     default:
     102           0 :       err = gpg_error (GPG_ERR_PUBKEY_ALGO);
     103           0 :       break;
     104             :     }
     105             : 
     106          29 :   if (!err && !gcry_pk_get_keygrip (s_pkey, grip))
     107           0 :     err = gpg_error (GPG_ERR_INTERNAL);
     108             : 
     109          29 :   gcry_sexp_release (s_pkey);
     110          29 :   return err;
     111             : }
     112             : 
     113             : 
     114             : /* Convert a secret key given as algorithm id and an array of key
     115             :    parameters into our s-expression based format.  Note that
     116             :    PUBKEY_ALGO has an gcrypt algorithm number. */
     117             : static gpg_error_t
     118           8 : convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey,
     119             :                     const char *curve)
     120             : {
     121             :   gpg_error_t err;
     122           8 :   gcry_sexp_t s_skey = NULL;
     123             : 
     124           8 :   *r_key = NULL;
     125             : 
     126           8 :   switch (pubkey_algo)
     127             :     {
     128             :     case GCRY_PK_DSA:
     129           0 :       err = gcry_sexp_build (&s_skey, NULL,
     130             :                              "(private-key(dsa(p%m)(q%m)(g%m)(y%m)(x%m)))",
     131           0 :                              skey[0], skey[1], skey[2], skey[3], skey[4]);
     132           0 :       break;
     133             : 
     134             :     case GCRY_PK_ELG:
     135             :     case GCRY_PK_ELG_E:
     136           0 :       err = gcry_sexp_build (&s_skey, NULL,
     137             :                              "(private-key(elg(p%m)(g%m)(y%m)(x%m)))",
     138           0 :                              skey[0], skey[1], skey[2], skey[3]);
     139           0 :       break;
     140             : 
     141             : 
     142             :     case GCRY_PK_RSA:
     143             :     case GCRY_PK_RSA_E:
     144             :     case GCRY_PK_RSA_S:
     145          10 :       err = gcry_sexp_build (&s_skey, NULL,
     146             :                              "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
     147           8 :                              skey[0], skey[1], skey[2], skey[3], skey[4],
     148           2 :                              skey[5]);
     149           2 :       break;
     150             : 
     151             :     case GCRY_PK_ECC:
     152           6 :       if (!curve)
     153           0 :         err = gpg_error (GPG_ERR_BAD_SECKEY);
     154             :       else
     155             :         {
     156             :           const char *format;
     157             : 
     158           6 :           if (!strcmp (curve, "Ed25519"))
     159             :             /* Do not store the OID as name but the real name and the
     160             :                EdDSA flag.  */
     161           0 :             format = "(private-key(ecc(curve %s)(flags eddsa)(q%m)(d%m)))";
     162           6 :           else if (!strcmp (curve, "Curve25519"))
     163           0 :             format = "(private-key(ecc(curve %s)(flags djb-tweak)(q%m)(d%m)))";
     164             :           else
     165           6 :             format = "(private-key(ecc(curve %s)(q%m)(d%m)))";
     166             : 
     167           6 :           err = gcry_sexp_build (&s_skey, NULL, format, curve, skey[0], skey[1]);
     168             :         }
     169           6 :       break;
     170             : 
     171             :     default:
     172           0 :       err = gpg_error (GPG_ERR_PUBKEY_ALGO);
     173           0 :       break;
     174             :     }
     175             : 
     176           8 :   if (!err)
     177           8 :     *r_key = s_skey;
     178           8 :   return err;
     179             : }
     180             : 
     181             : 
     182             : /* Convert a secret key given as algorithm id, an array of key
     183             :    parameters, and an S-expression of the original OpenPGP transfer
     184             :    key into our s-expression based format.  This is a variant of
     185             :    convert_secret_key which is used for the openpgp-native protection
     186             :    mode.  Note that PUBKEY_ALGO has an gcrypt algorithm number. */
     187             : static gpg_error_t
     188          19 : convert_transfer_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey,
     189             :                       const char *curve, gcry_sexp_t transfer_key)
     190             : {
     191             :   gpg_error_t err;
     192          19 :   gcry_sexp_t s_skey = NULL;
     193             : 
     194          19 :   *r_key = NULL;
     195             : 
     196          19 :   switch (pubkey_algo)
     197             :     {
     198             :     case GCRY_PK_DSA:
     199           6 :       err = gcry_sexp_build
     200             :         (&s_skey, NULL,
     201             :          "(protected-private-key(dsa(p%m)(q%m)(g%m)(y%m)"
     202             :          "(protected openpgp-native%S)))",
     203           6 :          skey[0], skey[1], skey[2], skey[3], transfer_key);
     204           2 :       break;
     205             : 
     206             :     case GCRY_PK_ELG:
     207           4 :       err = gcry_sexp_build
     208             :         (&s_skey, NULL,
     209             :          "(protected-private-key(elg(p%m)(g%m)(y%m)"
     210             :          "(protected openpgp-native%S)))",
     211           4 :          skey[0], skey[1], skey[2], transfer_key);
     212           2 :       break;
     213             : 
     214             : 
     215             :     case GCRY_PK_RSA:
     216           3 :       err = gcry_sexp_build
     217             :         (&s_skey, NULL,
     218             :          "(protected-private-key(rsa(n%m)(e%m)"
     219             :          "(protected openpgp-native%S)))",
     220           3 :          skey[0], skey[1], transfer_key );
     221           3 :       break;
     222             : 
     223             :     case GCRY_PK_ECC:
     224          12 :       if (!curve)
     225           0 :         err = gpg_error (GPG_ERR_BAD_SECKEY);
     226             :       else
     227             :         {
     228             :           const char *format;
     229             : 
     230          12 :           if (!strcmp (curve, "Ed25519"))
     231             :             /* Do not store the OID as name but the real name and the
     232             :                EdDSA flag.  */
     233           0 :             format = "(protected-private-key(ecc(curve %s)(flags eddsa)(q%m)"
     234             :               "(protected openpgp-native%S)))";
     235          12 :           else if (!strcmp (curve, "Curve25519"))
     236           0 :             format = "(protected-private-key(ecc(curve %s)(flags djb-tweak)(q%m)"
     237             :               "(protected openpgp-native%S)))";
     238             :           else
     239          12 :             format = "(protected-private-key(ecc(curve %s)(q%m)"
     240             :               "(protected openpgp-native%S)))";
     241             : 
     242          12 :           err = gcry_sexp_build (&s_skey, NULL, format, curve, skey[0], transfer_key);
     243             :         }
     244          12 :       break;
     245             : 
     246             :     default:
     247           0 :       err = gpg_error (GPG_ERR_PUBKEY_ALGO);
     248           0 :       break;
     249             :     }
     250             : 
     251          19 :   if (!err)
     252          19 :     *r_key = s_skey;
     253          19 :   return err;
     254             : }
     255             : 
     256             : 
     257             : /* Hash the passphrase and set the key. */
     258             : static gpg_error_t
     259           8 : hash_passphrase_and_set_key (const char *passphrase,
     260             :                              gcry_cipher_hd_t hd, int protect_algo,
     261             :                              int s2k_mode, int s2k_algo,
     262             :                              byte *s2k_salt, u32 s2k_count)
     263             : {
     264             :   gpg_error_t err;
     265             :   unsigned char *key;
     266             :   size_t keylen;
     267             : 
     268           8 :   keylen = gcry_cipher_get_algo_keylen (protect_algo);
     269           8 :   if (!keylen)
     270           0 :     return gpg_error (GPG_ERR_INTERNAL);
     271             : 
     272           8 :   key = xtrymalloc_secure (keylen);
     273           8 :   if (!key)
     274           0 :     return gpg_error_from_syserror ();
     275             : 
     276           8 :   err = s2k_hash_passphrase (passphrase,
     277             :                              s2k_algo, s2k_mode, s2k_salt, s2k_count,
     278             :                              key, keylen);
     279           8 :   if (!err)
     280           8 :     err = gcry_cipher_setkey (hd, key, keylen);
     281             : 
     282           8 :   xfree (key);
     283           8 :   return err;
     284             : }
     285             : 
     286             : 
     287             : static u16
     288           8 : checksum (const unsigned char *p, unsigned int n)
     289             : {
     290             :   u16 a;
     291             : 
     292         664 :   for (a=0; n; n-- )
     293         656 :     a += *p++;
     294           8 :   return a;
     295             : }
     296             : 
     297             : 
     298             : /* Return the number of expected key parameters.  */
     299             : static void
     300          56 : get_npkey_nskey (int pubkey_algo, size_t *npkey, size_t *nskey)
     301             : {
     302          56 :   switch (pubkey_algo)
     303             :     {
     304          10 :     case GCRY_PK_RSA:   *npkey = 2; *nskey = 6; break;
     305           5 :     case GCRY_PK_ELG:   *npkey = 3; *nskey = 4; break;
     306           0 :     case GCRY_PK_ELG_E: *npkey = 3; *nskey = 4; break;
     307           5 :     case GCRY_PK_DSA:   *npkey = 4; *nskey = 5; break;
     308          36 :     case GCRY_PK_ECC:   *npkey = 1; *nskey = 2; break;
     309           0 :     default:            *npkey = 0; *nskey = 0; break;
     310             :     }
     311          56 : }
     312             : 
     313             : 
     314             : /* Helper for do_unprotect.  PUBKEY_ALOGO is the gcrypt algo number.
     315             :    On success R_NPKEY and R_NSKEY receive the number or parameters for
     316             :    the algorithm PUBKEY_ALGO and R_SKEYLEN the used length of
     317             :    SKEY.  */
     318             : static int
     319          27 : prepare_unprotect (int pubkey_algo, gcry_mpi_t *skey, size_t skeysize,
     320             :                    int s2k_mode,
     321             :                    unsigned int *r_npkey, unsigned int *r_nskey,
     322             :                    unsigned int *r_skeylen)
     323             : {
     324             :   size_t npkey, nskey, skeylen;
     325             :   int i;
     326             : 
     327             :   /* Count the actual number of MPIs is in the array and set the
     328             :      remainder to NULL for easier processing later on.  */
     329          27 :   for (skeylen = 0; skey[skeylen]; skeylen++)
     330             :     ;
     331         216 :   for (i=skeylen; i < skeysize; i++)
     332         189 :     skey[i] = NULL;
     333             : 
     334             :   /* Check some args.  */
     335          27 :   if (s2k_mode == 1001)
     336             :     {
     337             :       /* Stub key.  */
     338           0 :       log_info (_("secret key parts are not available\n"));
     339           0 :       return gpg_error (GPG_ERR_UNUSABLE_SECKEY);
     340             :     }
     341             : 
     342          27 :   if (gcry_pk_test_algo (pubkey_algo))
     343             :     {
     344           0 :       log_info (_("public key algorithm %d (%s) is not supported\n"),
     345             :                 pubkey_algo, gcry_pk_algo_name (pubkey_algo));
     346           0 :       return gpg_error (GPG_ERR_PUBKEY_ALGO);
     347             :     }
     348             : 
     349             :   /* Get properties of the public key algorithm and do some
     350             :      consistency checks.  Note that we need at least NPKEY+1 elements
     351             :      in the SKEY array. */
     352          27 :   get_npkey_nskey (pubkey_algo, &npkey, &nskey);
     353          27 :   if (!npkey || !nskey || npkey >= nskey)
     354           0 :     return gpg_error (GPG_ERR_INTERNAL);
     355          27 :   if (skeylen <= npkey)
     356           0 :     return gpg_error (GPG_ERR_MISSING_VALUE);
     357          27 :   if (nskey+1 >= skeysize)
     358           0 :     return gpg_error (GPG_ERR_BUFFER_TOO_SHORT);
     359             : 
     360             :   /* Check that the public key parameters are all available and not
     361             :      encrypted.  */
     362          69 :   for (i=0; i < npkey; i++)
     363             :     {
     364          42 :       if (!skey[i] || gcry_mpi_get_flag (skey[i], GCRYMPI_FLAG_USER1))
     365           0 :         return gpg_error (GPG_ERR_BAD_SECKEY);
     366             :     }
     367             : 
     368          27 :   if (r_npkey)
     369           8 :     *r_npkey = npkey;
     370          27 :   if (r_nskey)
     371           8 :     *r_nskey = nskey;
     372          27 :   if (r_skeylen)
     373           8 :     *r_skeylen = skeylen;
     374          27 :   return 0;
     375             : }
     376             : 
     377             : 
     378             : /* Note that this function modifies SKEY.  SKEYSIZE is the allocated
     379             :    size of the array including the NULL item; this is used for a
     380             :    bounds check.  On success a converted key is stored at R_KEY.  */
     381             : static int
     382           8 : do_unprotect (const char *passphrase,
     383             :               int pkt_version, int pubkey_algo, int is_protected,
     384             :               const char *curve, gcry_mpi_t *skey, size_t skeysize,
     385             :               int protect_algo, void *protect_iv, size_t protect_ivlen,
     386             :               int s2k_mode, int s2k_algo, byte *s2k_salt, u32 s2k_count,
     387             :               u16 desired_csum, gcry_sexp_t *r_key)
     388             : {
     389             :   gpg_error_t err;
     390             :   unsigned int npkey, nskey, skeylen;
     391           8 :   gcry_cipher_hd_t cipher_hd = NULL;
     392             :   u16 actual_csum;
     393             :   size_t nbytes;
     394             :   int i;
     395             :   gcry_mpi_t tmpmpi;
     396             : 
     397           8 :   *r_key = NULL;
     398             : 
     399           8 :   err = prepare_unprotect (pubkey_algo, skey, skeysize, s2k_mode,
     400             :                            &npkey, &nskey, &skeylen);
     401           8 :   if (err)
     402           0 :     return err;
     403             : 
     404             :   /* Check whether SKEY is at all protected.  If it is not protected
     405             :      merely verify the checksum.  */
     406           8 :   if (!is_protected)
     407             :     {
     408           2 :       actual_csum = 0;
     409          10 :       for (i=npkey; i < nskey; i++)
     410             :         {
     411           8 :           if (!skey[i] || gcry_mpi_get_flag (skey[i], GCRYMPI_FLAG_USER1))
     412           0 :             return gpg_error (GPG_ERR_BAD_SECKEY);
     413             : 
     414           8 :           if (gcry_mpi_get_flag (skey[i], GCRYMPI_FLAG_OPAQUE))
     415             :             {
     416             :               unsigned int nbits;
     417             :               const unsigned char *buffer;
     418           0 :               buffer = gcry_mpi_get_opaque (skey[i], &nbits);
     419           0 :               nbytes = (nbits+7)/8;
     420           0 :               actual_csum += checksum (buffer, nbytes);
     421             :             }
     422             :           else
     423             :             {
     424             :               unsigned char *buffer;
     425             : 
     426           8 :               err = gcry_mpi_aprint (GCRYMPI_FMT_PGP, &buffer, &nbytes,
     427           8 :                                      skey[i]);
     428           8 :               if (!err)
     429           8 :                 actual_csum += checksum (buffer, nbytes);
     430           8 :               xfree (buffer);
     431             :             }
     432           8 :           if (err)
     433           0 :             return err;
     434             :         }
     435             : 
     436           2 :       if (actual_csum != desired_csum)
     437           0 :         return gpg_error (GPG_ERR_CHECKSUM);
     438             : 
     439           2 :       goto do_convert;
     440             :     }
     441             : 
     442             : 
     443           6 :   if (gcry_cipher_test_algo (protect_algo))
     444             :     {
     445             :       /* The algorithm numbers are Libgcrypt numbers but fortunately
     446             :          the OpenPGP algorithm numbers map one-to-one to the Libgcrypt
     447             :          numbers.  */
     448           0 :       log_info (_("protection algorithm %d (%s) is not supported\n"),
     449             :                 protect_algo, gnupg_cipher_algo_name (protect_algo));
     450           0 :       return gpg_error (GPG_ERR_CIPHER_ALGO);
     451             :     }
     452             : 
     453           6 :   if (gcry_md_test_algo (s2k_algo))
     454             :     {
     455           0 :       log_info (_("protection hash algorithm %d (%s) is not supported\n"),
     456             :                 s2k_algo, gcry_md_algo_name (s2k_algo));
     457           0 :       return gpg_error (GPG_ERR_DIGEST_ALGO);
     458             :     }
     459             : 
     460           6 :   err = gcry_cipher_open (&cipher_hd, protect_algo,
     461             :                           GCRY_CIPHER_MODE_CFB,
     462             :                           (GCRY_CIPHER_SECURE
     463             :                            | (protect_algo >= 100 ?
     464             :                               0 : GCRY_CIPHER_ENABLE_SYNC)));
     465           6 :   if (err)
     466             :     {
     467           0 :       log_error ("failed to open cipher_algo %d: %s\n",
     468             :                  protect_algo, gpg_strerror (err));
     469           0 :       return err;
     470             :     }
     471             : 
     472           6 :   err = hash_passphrase_and_set_key (passphrase, cipher_hd, protect_algo,
     473             :                                      s2k_mode, s2k_algo, s2k_salt, s2k_count);
     474           6 :   if (err)
     475             :     {
     476           0 :       gcry_cipher_close (cipher_hd);
     477           0 :       return err;
     478             :     }
     479             : 
     480           6 :   gcry_cipher_setiv (cipher_hd, protect_iv, protect_ivlen);
     481             : 
     482           6 :   actual_csum = 0;
     483           6 :   if (pkt_version >= 4)
     484             :     {
     485             :       int ndata;
     486             :       unsigned int ndatabits;
     487             :       const unsigned char *p;
     488             :       unsigned char *data;
     489           6 :       u16 csum_pgp7 = 0;
     490             : 
     491           6 :       if (!gcry_mpi_get_flag (skey[npkey], GCRYMPI_FLAG_OPAQUE ))
     492             :         {
     493           0 :           gcry_cipher_close (cipher_hd);
     494           0 :           return gpg_error (GPG_ERR_BAD_SECKEY);
     495             :         }
     496           6 :       p = gcry_mpi_get_opaque (skey[npkey], &ndatabits);
     497           6 :       ndata = (ndatabits+7)/8;
     498             : 
     499           6 :       if (ndata > 1)
     500           6 :         csum_pgp7 = buf16_to_u16 (p+ndata-2);
     501           6 :       data = xtrymalloc_secure (ndata);
     502           6 :       if (!data)
     503             :         {
     504           0 :           err = gpg_error_from_syserror ();
     505           0 :           gcry_cipher_close (cipher_hd);
     506           0 :           return err;
     507             :         }
     508           6 :       gcry_cipher_decrypt (cipher_hd, data, ndata, p, ndata);
     509             : 
     510           6 :       p = data;
     511           6 :       if (is_protected == 2)
     512             :         {
     513             :           /* This is the new SHA1 checksum method to detect tampering
     514             :              with the key as used by the Klima/Rosa attack.  */
     515           6 :           desired_csum = 0;
     516           6 :           actual_csum = 1;  /* Default to bad checksum.  */
     517             : 
     518           6 :           if (ndata < 20)
     519           0 :             log_error ("not enough bytes for SHA-1 checksum\n");
     520             :           else
     521             :             {
     522             :               gcry_md_hd_t h;
     523             : 
     524           6 :               if (gcry_md_open (&h, GCRY_MD_SHA1, 1))
     525           0 :                 BUG(); /* Algo not available. */
     526           6 :               gcry_md_write (h, data, ndata - 20);
     527           6 :               gcry_md_final (h);
     528           6 :               if (!memcmp (gcry_md_read (h, GCRY_MD_SHA1), data+ndata-20, 20))
     529           6 :                 actual_csum = 0; /* Digest does match.  */
     530           6 :               gcry_md_close (h);
     531             :             }
     532             :         }
     533             :       else
     534             :         {
     535             :           /* Old 16 bit checksum method.  */
     536           0 :           if (ndata < 2)
     537             :             {
     538           0 :               log_error ("not enough bytes for checksum\n");
     539           0 :               desired_csum = 0;
     540           0 :               actual_csum = 1;  /* Mark checksum bad.  */
     541             :             }
     542             :           else
     543             :             {
     544           0 :               desired_csum = buf16_to_u16 (data+ndata-2);
     545           0 :               actual_csum = checksum (data, ndata-2);
     546           0 :               if (desired_csum != actual_csum)
     547             :                 {
     548             :                   /* This is a PGP 7.0.0 workaround */
     549           0 :                   desired_csum = csum_pgp7; /* Take the encrypted one.  */
     550             :                 }
     551             :             }
     552             :         }
     553             : 
     554             :       /* Better check it here.  Otherwise the gcry_mpi_scan would fail
     555             :          because the length may have an arbitrary value.  */
     556           6 :       if (desired_csum == actual_csum)
     557             :         {
     558          12 :           for (i=npkey; i < nskey; i++ )
     559             :             {
     560           6 :               if (gcry_mpi_scan (&tmpmpi, GCRYMPI_FMT_PGP, p, ndata, &nbytes))
     561             :                 {
     562             :                   /* Checksum was okay, but not correctly decrypted.  */
     563           0 :                   desired_csum = 0;
     564           0 :                   actual_csum = 1;   /* Mark checksum bad.  */
     565           0 :                   break;
     566             :                 }
     567           6 :               gcry_mpi_release (skey[i]);
     568           6 :               skey[i] = tmpmpi;
     569           6 :               ndata -= nbytes;
     570           6 :               p += nbytes;
     571             :             }
     572           6 :           skey[i] = NULL;
     573           6 :           skeylen = i;
     574           6 :           assert (skeylen <= skeysize);
     575             : 
     576             :           /* Note: at this point NDATA should be 2 for a simple
     577             :              checksum or 20 for the sha1 digest.  */
     578             :         }
     579           6 :       xfree(data);
     580             :     }
     581             :   else /* Packet version <= 3.  */
     582             :     {
     583             :       unsigned char *buffer;
     584             : 
     585           0 :       for (i = npkey; i < nskey; i++)
     586             :         {
     587             :           const unsigned char *p;
     588             :           size_t ndata;
     589             :           unsigned int ndatabits;
     590             : 
     591           0 :           if (!skey[i] || !gcry_mpi_get_flag (skey[i], GCRYMPI_FLAG_OPAQUE))
     592             :             {
     593           0 :               gcry_cipher_close (cipher_hd);
     594           0 :               return gpg_error (GPG_ERR_BAD_SECKEY);
     595             :             }
     596           0 :           p = gcry_mpi_get_opaque (skey[i], &ndatabits);
     597           0 :           ndata = (ndatabits+7)/8;
     598             : 
     599           0 :           if (!(ndata >= 2) || !(ndata == (buf16_to_ushort (p) + 7)/8 + 2))
     600             :             {
     601           0 :               gcry_cipher_close (cipher_hd);
     602           0 :               return gpg_error (GPG_ERR_BAD_SECKEY);
     603             :             }
     604             : 
     605           0 :           buffer = xtrymalloc_secure (ndata);
     606           0 :           if (!buffer)
     607             :             {
     608           0 :               err = gpg_error_from_syserror ();
     609           0 :               gcry_cipher_close (cipher_hd);
     610           0 :               return err;
     611             :             }
     612             : 
     613           0 :           gcry_cipher_sync (cipher_hd);
     614           0 :           buffer[0] = p[0];
     615           0 :           buffer[1] = p[1];
     616           0 :           gcry_cipher_decrypt (cipher_hd, buffer+2, ndata-2, p+2, ndata-2);
     617           0 :           actual_csum += checksum (buffer, ndata);
     618           0 :           err = gcry_mpi_scan (&tmpmpi, GCRYMPI_FMT_PGP, buffer, ndata, &ndata);
     619           0 :           xfree (buffer);
     620           0 :           if (err)
     621             :             {
     622             :               /* Checksum was okay, but not correctly decrypted.  */
     623           0 :               desired_csum = 0;
     624           0 :               actual_csum = 1;   /* Mark checksum bad.  */
     625           0 :               break;
     626             :             }
     627           0 :           gcry_mpi_release (skey[i]);
     628           0 :           skey[i] = tmpmpi;
     629             :         }
     630             :     }
     631           6 :   gcry_cipher_close (cipher_hd);
     632             : 
     633             :   /* Now let's see whether we have used the correct passphrase. */
     634           6 :   if (actual_csum != desired_csum)
     635           0 :     return gpg_error (GPG_ERR_BAD_PASSPHRASE);
     636             : 
     637             :  do_convert:
     638           8 :   if (nskey != skeylen)
     639           0 :     err = gpg_error (GPG_ERR_BAD_SECKEY);
     640             :   else
     641           8 :     err = convert_secret_key (r_key, pubkey_algo, skey, curve);
     642           8 :   if (err)
     643           0 :     return err;
     644             : 
     645             :   /* The checksum may fail, thus we also check the key itself.  */
     646           8 :   err = gcry_pk_testkey (*r_key);
     647           8 :   if (err)
     648             :     {
     649           0 :       gcry_sexp_release (*r_key);
     650           0 :       *r_key = NULL;
     651           0 :       return gpg_error (GPG_ERR_BAD_PASSPHRASE);
     652             :     }
     653             : 
     654           8 :   return 0;
     655             : }
     656             : 
     657             : 
     658             : /* Callback function to try the unprotection from the passphrase query
     659             :    code.  */
     660             : static gpg_error_t
     661           8 : try_do_unprotect_cb (struct pin_entry_info_s *pi)
     662             : {
     663             :   gpg_error_t err;
     664           8 :   struct try_do_unprotect_arg_s *arg = pi->check_cb_arg;
     665             : 
     666          40 :   err = do_unprotect (pi->pin,
     667           8 :                       arg->is_v4? 4:3,
     668             :                       arg->pubkey_algo, arg->is_protected,
     669             :                       arg->curve,
     670             :                       arg->skey, arg->skeysize,
     671          16 :                       arg->protect_algo, arg->iv, arg->ivlen,
     672             :                       arg->s2k_mode, arg->s2k_algo,
     673             :                       arg->s2k_salt, arg->s2k_count,
     674           8 :                       arg->desired_csum, arg->r_key);
     675             :   /* SKEY may be modified now, thus we need to re-compute SKEYIDX.  */
     676          40 :   for (arg->skeyidx = 0; (arg->skeyidx < arg->skeysize
     677          56 :                           && arg->skey[arg->skeyidx]); arg->skeyidx++)
     678             :     ;
     679           8 :   return err;
     680             : }
     681             : 
     682             : 
     683             : /* See convert_from_openpgp for the core of the description.  This
     684             :    function adds an optional PASSPHRASE argument and uses this to
     685             :    silently decrypt the key; CACHE_NONCE and R_PASSPHRASE must both be
     686             :    NULL in this mode.  */
     687             : static gpg_error_t
     688          29 : convert_from_openpgp_main (ctrl_t ctrl, gcry_sexp_t s_pgp, int dontcare_exist,
     689             :                            unsigned char *grip, const char *prompt,
     690             :                            const char *cache_nonce, const char *passphrase,
     691             :                            unsigned char **r_key, char **r_passphrase)
     692             : {
     693             :   gpg_error_t err;
     694             :   int unattended;
     695             :   int from_native;
     696             :   gcry_sexp_t top_list;
     697          29 :   gcry_sexp_t list = NULL;
     698             :   const char *value;
     699             :   size_t valuelen;
     700             :   char *string;
     701             :   int  idx;
     702             :   int  is_v4, is_protected;
     703             :   int  pubkey_algo;
     704          29 :   int  protect_algo = 0;
     705             :   char iv[16];
     706          29 :   int  ivlen = 0;
     707          29 :   int  s2k_mode = 0;
     708          29 :   int  s2k_algo = 0;
     709             :   byte s2k_salt[8];
     710          29 :   u32  s2k_count = 0;
     711             :   size_t npkey, nskey;
     712             :   gcry_mpi_t skey[10];  /* We support up to 9 parameters.  */
     713          29 :   char *curve = NULL;
     714             :   u16 desired_csum;
     715          29 :   int skeyidx = 0;
     716          29 :   gcry_sexp_t s_skey = NULL;
     717             : 
     718          29 :   *r_key = NULL;
     719          29 :   if (r_passphrase)
     720           0 :     *r_passphrase = NULL;
     721          29 :   unattended = !r_passphrase;
     722          29 :   from_native = (!cache_nonce && passphrase && !r_passphrase);
     723             : 
     724          29 :   top_list = gcry_sexp_find_token (s_pgp, "openpgp-private-key", 0);
     725          29 :   if (!top_list)
     726           0 :     goto bad_seckey;
     727             : 
     728          29 :   list = gcry_sexp_find_token (top_list, "version", 0);
     729          29 :   if (!list)
     730           0 :     goto bad_seckey;
     731          29 :   value = gcry_sexp_nth_data (list, 1, &valuelen);
     732          29 :   if (!value || valuelen != 1 || !(value[0] == '3' || value[0] == '4'))
     733             :     goto bad_seckey;
     734          29 :   is_v4 = (value[0] == '4');
     735             : 
     736          29 :   gcry_sexp_release (list);
     737          29 :   list = gcry_sexp_find_token (top_list, "protection", 0);
     738          29 :   if (!list)
     739           0 :     goto bad_seckey;
     740          29 :   value = gcry_sexp_nth_data (list, 1, &valuelen);
     741          29 :   if (!value)
     742           0 :     goto bad_seckey;
     743          29 :   if (valuelen == 4 && !memcmp (value, "sha1", 4))
     744          25 :     is_protected = 2;
     745           4 :   else if (valuelen == 3 && !memcmp (value, "sum", 3))
     746           0 :     is_protected = 1;
     747           4 :   else if (valuelen == 4 && !memcmp (value, "none", 4))
     748           4 :     is_protected = 0;
     749             :   else
     750             :     goto bad_seckey;
     751             : 
     752          29 :   if (is_protected)
     753             :     {
     754          25 :       string = gcry_sexp_nth_string (list, 2);
     755          25 :       if (!string)
     756           0 :         goto bad_seckey;
     757          25 :       protect_algo = gcry_cipher_map_name (string);
     758          25 :       xfree (string);
     759             : 
     760          25 :       value = gcry_sexp_nth_data (list, 3, &valuelen);
     761          25 :       if (!value || !valuelen || valuelen > sizeof iv)
     762             :         goto bad_seckey;
     763          25 :       memcpy (iv, value, valuelen);
     764          25 :       ivlen = valuelen;
     765             : 
     766          25 :       string = gcry_sexp_nth_string (list, 4);
     767          25 :       if (!string)
     768           0 :         goto bad_seckey;
     769          25 :       s2k_mode = strtol (string, NULL, 10);
     770          25 :       xfree (string);
     771             : 
     772          25 :       string = gcry_sexp_nth_string (list, 5);
     773          25 :       if (!string)
     774           0 :         goto bad_seckey;
     775          25 :       s2k_algo = gcry_md_map_name (string);
     776          25 :       xfree (string);
     777             : 
     778          25 :       value = gcry_sexp_nth_data (list, 6, &valuelen);
     779          25 :       if (!value || !valuelen || valuelen > sizeof s2k_salt)
     780             :         goto bad_seckey;
     781          25 :       memcpy (s2k_salt, value, valuelen);
     782             : 
     783          25 :       string = gcry_sexp_nth_string (list, 7);
     784          25 :       if (!string)
     785           0 :         goto bad_seckey;
     786          25 :       s2k_count = strtoul (string, NULL, 10);
     787          25 :       xfree (string);
     788             :     }
     789             : 
     790          29 :   gcry_sexp_release (list);
     791          29 :   list = gcry_sexp_find_token (top_list, "algo", 0);
     792          29 :   if (!list)
     793           0 :     goto bad_seckey;
     794          29 :   string = gcry_sexp_nth_string (list, 1);
     795          29 :   if (!string)
     796           0 :     goto bad_seckey;
     797          29 :   pubkey_algo = gcry_pk_map_name (string);
     798          29 :   xfree (string);
     799             : 
     800          29 :   get_npkey_nskey (pubkey_algo, &npkey, &nskey);
     801          29 :   if (!npkey || !nskey || npkey >= nskey)
     802             :     goto bad_seckey;
     803             : 
     804          29 :   if (npkey == 1) /* This is ECC */
     805             :     {
     806          18 :       gcry_sexp_release (list);
     807          18 :       list = gcry_sexp_find_token (top_list, "curve", 0);
     808          18 :       if (!list)
     809           0 :         goto bad_seckey;
     810          18 :       curve = gcry_sexp_nth_string (list, 1);
     811          18 :       if (!curve)
     812           0 :         goto bad_seckey;
     813             :     }
     814             : 
     815          29 :   gcry_sexp_release (list);
     816          29 :   list = gcry_sexp_find_token (top_list, "skey", 0);
     817          29 :   if (!list)
     818           0 :     goto bad_seckey;
     819          29 :   for (idx=0;;)
     820             :     {
     821             :       int is_enc;
     822             : 
     823         119 :       value = gcry_sexp_nth_data (list, ++idx, &valuelen);
     824         119 :       if (!value && skeyidx >= npkey)
     825          29 :         break;  /* Ready.  */
     826             : 
     827             :       /* Check for too many parameters.  Note that depending on the
     828             :          protection mode and version number we may see less than NSKEY
     829             :          (but at least NPKEY+1) parameters.  */
     830          90 :       if (idx >= 2*nskey)
     831           0 :         goto bad_seckey;
     832          90 :       if (skeyidx >= DIM (skey)-1)
     833           0 :         goto bad_seckey;
     834             : 
     835          90 :       if (!value || valuelen != 1 || !(value[0] == '_' || value[0] == 'e'))
     836             :         goto bad_seckey;
     837          90 :       is_enc = (value[0] == 'e');
     838          90 :       value = gcry_sexp_nth_data (list, ++idx, &valuelen);
     839          90 :       if (!value || !valuelen)
     840             :         goto bad_seckey;
     841          90 :       if (is_enc)
     842             :         {
     843             :           /* Encrypted parameters need to be stored as opaque.  */
     844          25 :           skey[skeyidx] = gcry_mpi_set_opaque_copy (NULL, value, valuelen*8);
     845          25 :           if (!skey[skeyidx])
     846           0 :             goto outofmem;
     847          25 :           gcry_mpi_set_flag (skey[skeyidx], GCRYMPI_FLAG_USER1);
     848             :         }
     849             :       else
     850             :         {
     851          65 :           if (gcry_mpi_scan (skey + skeyidx, GCRYMPI_FMT_STD,
     852             :                              value, valuelen, NULL))
     853           0 :             goto bad_seckey;
     854             :         }
     855          90 :       skeyidx++;
     856          90 :     }
     857          29 :   skey[skeyidx++] = NULL;
     858             : 
     859          29 :   gcry_sexp_release (list);
     860          29 :   list = gcry_sexp_find_token (top_list, "csum", 0);
     861          29 :   if (list)
     862             :     {
     863          29 :       string = gcry_sexp_nth_string (list, 1);
     864          29 :       if (!string)
     865           0 :         goto bad_seckey;
     866          29 :       desired_csum = strtoul (string, NULL, 10);
     867          29 :       xfree (string);
     868             :     }
     869             :   else
     870           0 :     desired_csum = 0;
     871             : 
     872             : 
     873          29 :   gcry_sexp_release (list); list = NULL;
     874          29 :   gcry_sexp_release (top_list); top_list = NULL;
     875             : 
     876             : #if 0
     877             :   log_debug ("XXX is_v4=%d\n", is_v4);
     878             :   log_debug ("XXX pubkey_algo=%d\n", pubkey_algo);
     879             :   log_debug ("XXX is_protected=%d\n", is_protected);
     880             :   log_debug ("XXX protect_algo=%d\n", protect_algo);
     881             :   log_printhex ("XXX iv", iv, ivlen);
     882             :   log_debug ("XXX ivlen=%d\n", ivlen);
     883             :   log_debug ("XXX s2k_mode=%d\n", s2k_mode);
     884             :   log_debug ("XXX s2k_algo=%d\n", s2k_algo);
     885             :   log_printhex ("XXX s2k_salt", s2k_salt, sizeof s2k_salt);
     886             :   log_debug ("XXX s2k_count=%lu\n", (unsigned long)s2k_count);
     887             :   log_debug ("XXX curve='%s'\n", curve);
     888             :   for (idx=0; skey[idx]; idx++)
     889             :     gcry_log_debugmpi (gcry_mpi_get_flag (skey[idx], GCRYMPI_FLAG_USER1)
     890             :                        ? "skey(e)" : "skey(_)", skey[idx]);
     891             : #endif /*0*/
     892             : 
     893          29 :   err = get_keygrip (pubkey_algo, curve, skey, grip);
     894          29 :   if (err)
     895           0 :     goto leave;
     896             : 
     897          29 :   if (!dontcare_exist && !from_native && !agent_key_available (grip))
     898             :     {
     899           2 :       err = gpg_error (GPG_ERR_EEXIST);
     900           2 :       goto leave;
     901             :     }
     902             : 
     903          27 :   if (unattended && !from_native)
     904             :     {
     905          19 :       err = prepare_unprotect (pubkey_algo, skey, DIM(skey), s2k_mode,
     906             :                                NULL, NULL, NULL);
     907          19 :       if (err)
     908           0 :         goto leave;
     909             : 
     910          19 :       err = convert_transfer_key (&s_skey, pubkey_algo, skey, curve, s_pgp);
     911          38 :       if (err)
     912           0 :         goto leave;
     913             :     }
     914             :   else
     915             :     {
     916             :       struct pin_entry_info_s *pi;
     917             :       struct try_do_unprotect_arg_s pi_arg;
     918             : 
     919           8 :       pi = xtrycalloc_secure (1, sizeof (*pi) + MAX_PASSPHRASE_LEN + 1);
     920           8 :       if (!pi)
     921           0 :         return gpg_error_from_syserror ();
     922           8 :       pi->max_length = MAX_PASSPHRASE_LEN + 1;
     923           8 :       pi->min_digits = 0;  /* We want a real passphrase.  */
     924           8 :       pi->max_digits = 16;
     925           8 :       pi->max_tries = 3;
     926           8 :       pi->check_cb = try_do_unprotect_cb;
     927           8 :       pi->check_cb_arg = &pi_arg;
     928           8 :       pi_arg.is_v4 = is_v4;
     929           8 :       pi_arg.is_protected = is_protected;
     930           8 :       pi_arg.pubkey_algo = pubkey_algo;
     931           8 :       pi_arg.curve = curve;
     932           8 :       pi_arg.protect_algo = protect_algo;
     933           8 :       pi_arg.iv = iv;
     934           8 :       pi_arg.ivlen = ivlen;
     935           8 :       pi_arg.s2k_mode = s2k_mode;
     936           8 :       pi_arg.s2k_algo = s2k_algo;
     937           8 :       pi_arg.s2k_salt = s2k_salt;
     938           8 :       pi_arg.s2k_count = s2k_count;
     939           8 :       pi_arg.desired_csum = desired_csum;
     940           8 :       pi_arg.skey = skey;
     941           8 :       pi_arg.skeysize = DIM (skey);
     942           8 :       pi_arg.skeyidx = skeyidx;
     943           8 :       pi_arg.r_key = &s_skey;
     944             : 
     945           8 :       err = gpg_error (GPG_ERR_BAD_PASSPHRASE);
     946           8 :       if (!is_protected)
     947             :         {
     948           2 :           err = try_do_unprotect_cb (pi);
     949             :         }
     950           6 :       else if (cache_nonce)
     951             :         {
     952             :           char *cache_value;
     953             : 
     954           0 :           cache_value = agent_get_cache (cache_nonce, CACHE_MODE_NONCE);
     955           0 :           if (cache_value)
     956             :             {
     957           0 :               if (strlen (cache_value) < pi->max_length)
     958           0 :                 strcpy (pi->pin, cache_value);
     959           0 :               xfree (cache_value);
     960             :             }
     961           0 :           if (*pi->pin)
     962           0 :             err = try_do_unprotect_cb (pi);
     963             :         }
     964           6 :       else if (from_native)
     965             :         {
     966           6 :           if (strlen (passphrase) < pi->max_length)
     967           6 :             strcpy (pi->pin, passphrase);
     968           6 :           err = try_do_unprotect_cb (pi);
     969             :         }
     970           8 :       if (gpg_err_code (err) == GPG_ERR_BAD_PASSPHRASE && !from_native)
     971           0 :         err = agent_askpin (ctrl, prompt, NULL, NULL, pi, NULL, 0);
     972           8 :       skeyidx = pi_arg.skeyidx;
     973           8 :       if (!err && r_passphrase && is_protected)
     974             :         {
     975           0 :           *r_passphrase = xtrystrdup (pi->pin);
     976           0 :           if (!*r_passphrase)
     977           0 :             err = gpg_error_from_syserror ();
     978             :         }
     979           8 :       xfree (pi);
     980           8 :       if (err)
     981           0 :         goto leave;
     982             :     }
     983             : 
     984             :   /* Save some memory and get rid of the SKEY array now.  */
     985         127 :   for (idx=0; idx < skeyidx; idx++)
     986         100 :     gcry_mpi_release (skey[idx]);
     987          27 :   skeyidx = 0;
     988             : 
     989             :   /* Note that the padding is not required - we use it only because
     990             :      that function allows us to create the result in secure memory.  */
     991          27 :   err = make_canon_sexp_pad (s_skey, 1, r_key, NULL);
     992             : 
     993             :  leave:
     994          29 :   xfree (curve);
     995          29 :   gcry_sexp_release (s_skey);
     996          29 :   gcry_sexp_release (list);
     997          29 :   gcry_sexp_release (top_list);
     998          40 :   for (idx=0; idx < skeyidx; idx++)
     999          11 :     gcry_mpi_release (skey[idx]);
    1000          29 :   if (err && r_passphrase)
    1001             :     {
    1002           0 :       xfree (*r_passphrase);
    1003           0 :       *r_passphrase = NULL;
    1004             :     }
    1005          29 :   return err;
    1006             : 
    1007             :  bad_seckey:
    1008           0 :   err = gpg_error (GPG_ERR_BAD_SECKEY);
    1009           0 :   goto leave;
    1010             : 
    1011             :  outofmem:
    1012           0 :   err = gpg_error (GPG_ERR_ENOMEM);
    1013           0 :   goto leave;
    1014             : 
    1015             : }
    1016             : 
    1017             : 
    1018             : /* Convert an OpenPGP transfer key into our internal format.  Before
    1019             :    asking for a passphrase we check whether the key already exists in
    1020             :    our key storage.  S_PGP is the OpenPGP key in transfer format.  If
    1021             :    CACHE_NONCE is given the passphrase will be looked up in the cache.
    1022             :    On success R_KEY will receive a canonical encoded S-expression with
    1023             :    the unprotected key in our internal format; the caller needs to
    1024             :    release that memory.  The passphrase used to decrypt the OpenPGP
    1025             :    key will be returned at R_PASSPHRASE; the caller must release this
    1026             :    passphrase.  If R_PASSPHRASE is NULL the unattended conversion mode
    1027             :    will be used which uses the openpgp-native protection format for
    1028             :    the key.  The keygrip will be stored at the 20 byte buffer pointed
    1029             :    to by GRIP.  On error NULL is stored at all return arguments.  */
    1030             : gpg_error_t
    1031          21 : convert_from_openpgp (ctrl_t ctrl, gcry_sexp_t s_pgp, int dontcare_exist,
    1032             :                       unsigned char *grip, const char *prompt,
    1033             :                       const char *cache_nonce,
    1034             :                       unsigned char **r_key, char **r_passphrase)
    1035             : {
    1036          21 :   return convert_from_openpgp_main (ctrl, s_pgp, dontcare_exist, grip, prompt,
    1037             :                                     cache_nonce, NULL,
    1038             :                                     r_key, r_passphrase);
    1039             : }
    1040             : 
    1041             : /* This function is called by agent_unprotect to re-protect an
    1042             :    openpgp-native protected private-key into the standard private-key
    1043             :    protection format.  */
    1044             : gpg_error_t
    1045           8 : convert_from_openpgp_native (ctrl_t ctrl,
    1046             :                              gcry_sexp_t s_pgp, const char *passphrase,
    1047             :                              unsigned char **r_key)
    1048             : {
    1049             :   gpg_error_t err;
    1050             :   unsigned char grip[20];
    1051             : 
    1052           8 :   if (!passphrase)
    1053           0 :     return gpg_error (GPG_ERR_INTERNAL);
    1054             : 
    1055           8 :   err = convert_from_openpgp_main (ctrl, s_pgp, 0, grip, NULL,
    1056             :                                    NULL, passphrase,
    1057             :                                    r_key, NULL);
    1058             : 
    1059             :   /* On success try to re-write the key.  */
    1060           8 :   if (!err)
    1061             :     {
    1062           8 :       if (*passphrase)
    1063             :         {
    1064           6 :           unsigned char *protectedkey = NULL;
    1065             :           size_t protectedkeylen;
    1066             : 
    1067           6 :           if (!agent_protect (*r_key, passphrase,
    1068             :                               &protectedkey, &protectedkeylen,
    1069             :                               ctrl->s2k_count, -1))
    1070           6 :             agent_write_private_key (grip, protectedkey, protectedkeylen, 1);
    1071           6 :           xfree (protectedkey);
    1072             :         }
    1073             :       else
    1074             :         {
    1075             :           /* Empty passphrase: write key without protection.  */
    1076           2 :           agent_write_private_key (grip,
    1077             :                                    *r_key,
    1078             :                                    gcry_sexp_canon_len (*r_key, 0, NULL,NULL),
    1079             :                                    1);
    1080             :         }
    1081             :     }
    1082             : 
    1083           8 :   return err;
    1084             : }
    1085             : 
    1086             : 
    1087             : /* Given an ARRAY of mpis with the key parameters, protect the secret
    1088             :    parameters in that array and replace them by one opaque encoded
    1089             :    mpi.  NPKEY is the number of public key parameters and NSKEY is
    1090             :    the number of secret key parameters (including the public ones).
    1091             :    On success the array will have NPKEY+1 elements.  */
    1092             : static gpg_error_t
    1093           2 : apply_protection (gcry_mpi_t *array, int npkey, int nskey,
    1094             :                   const char *passphrase,
    1095             :                   int protect_algo, void *protect_iv, size_t protect_ivlen,
    1096             :                   int s2k_mode, int s2k_algo, byte *s2k_salt, u32 s2k_count)
    1097             : {
    1098             :   gpg_error_t err;
    1099             :   int i, j;
    1100             :   gcry_cipher_hd_t cipherhd;
    1101             :   unsigned char *bufarr[10];
    1102             :   size_t narr[10];
    1103             :   unsigned int nbits[10];
    1104             :   int ndata;
    1105             :   unsigned char *p, *data;
    1106             : 
    1107           2 :   assert (npkey < nskey);
    1108           2 :   assert (nskey < DIM (bufarr));
    1109             : 
    1110             :   /* Collect only the secret key parameters into BUFARR et al and
    1111             :      compute the required size of the data buffer.  */
    1112           2 :   ndata = 20; /* Space for the SHA-1 checksum.  */
    1113           4 :   for (i = npkey, j = 0; i < nskey; i++, j++ )
    1114             :     {
    1115           2 :       err = gcry_mpi_aprint (GCRYMPI_FMT_USG, bufarr+j, narr+j, array[i]);
    1116           2 :       if (err)
    1117             :         {
    1118           0 :           for (i = 0; i < j; i++)
    1119           0 :             xfree (bufarr[i]);
    1120           0 :           return err;
    1121             :         }
    1122           2 :       nbits[j] = gcry_mpi_get_nbits (array[i]);
    1123           2 :       ndata += 2 + narr[j];
    1124             :     }
    1125             : 
    1126             :   /* Allocate data buffer and stuff it with the secret key parameters.  */
    1127           2 :   data = xtrymalloc_secure (ndata);
    1128           2 :   if (!data)
    1129             :     {
    1130           0 :       err = gpg_error_from_syserror ();
    1131           0 :       for (i = 0; i < (nskey-npkey); i++ )
    1132           0 :         xfree (bufarr[i]);
    1133           0 :       return err;
    1134             :     }
    1135           2 :   p = data;
    1136           4 :   for (i = 0; i < (nskey-npkey); i++ )
    1137             :     {
    1138           2 :       *p++ = nbits[i] >> 8 ;
    1139           2 :       *p++ = nbits[i];
    1140           2 :       memcpy (p, bufarr[i], narr[i]);
    1141           2 :       p += narr[i];
    1142           2 :       xfree (bufarr[i]);
    1143           2 :       bufarr[i] = NULL;
    1144             :     }
    1145           2 :   assert (p == data + ndata - 20);
    1146             : 
    1147             :   /* Append a hash of the secret key parameters.  */
    1148           2 :   gcry_md_hash_buffer (GCRY_MD_SHA1, p, data, ndata - 20);
    1149             : 
    1150             :   /* Encrypt it.  */
    1151           2 :   err = gcry_cipher_open (&cipherhd, protect_algo,
    1152             :                           GCRY_CIPHER_MODE_CFB, GCRY_CIPHER_SECURE);
    1153           2 :   if (!err)
    1154           2 :     err = hash_passphrase_and_set_key (passphrase, cipherhd, protect_algo,
    1155             :                                        s2k_mode, s2k_algo, s2k_salt, s2k_count);
    1156           2 :   if (!err)
    1157           2 :     err = gcry_cipher_setiv (cipherhd, protect_iv, protect_ivlen);
    1158           2 :   if (!err)
    1159           2 :     err = gcry_cipher_encrypt (cipherhd, data, ndata, NULL, 0);
    1160           2 :   gcry_cipher_close (cipherhd);
    1161           2 :   if (err)
    1162             :     {
    1163           0 :       xfree (data);
    1164           0 :       return err;
    1165             :     }
    1166             : 
    1167             :   /* Replace the secret key parameters in the array by one opaque value.  */
    1168           4 :   for (i = npkey; i < nskey; i++ )
    1169             :     {
    1170           2 :       gcry_mpi_release (array[i]);
    1171           2 :       array[i] = NULL;
    1172             :     }
    1173           2 :   array[npkey] = gcry_mpi_set_opaque (NULL, data, ndata*8);
    1174           2 :   return 0;
    1175             : }
    1176             : 
    1177             : 
    1178             : /*
    1179             :  * Examining S_KEY in S-Expression and extract data.
    1180             :  * When REQ_PRIVATE_KEY_DATA == 1, S_KEY's CAR should be 'private-key',
    1181             :  * but it also allows shadowed or protected versions.
    1182             :  * On success, it returns 0, otherwise error number.
    1183             :  * R_ALGONAME is static string which is no need to free by caller.
    1184             :  * R_NPKEY is pointer to number of public key data.
    1185             :  * R_NSKEY is pointer to number of private key data.
    1186             :  * R_ELEMS is static string which is no need to free by caller.
    1187             :  * ARRAY contains public and private key data.
    1188             :  * ARRAYSIZE is the allocated size of the array for cross-checking.
    1189             :  * R_CURVE is pointer to S-Expression of the curve (can be NULL).
    1190             :  * R_FLAGS is pointer to S-Expression of the flags (can be NULL).
    1191             :  */
    1192             : gpg_error_t
    1193          13 : extract_private_key (gcry_sexp_t s_key, int req_private_key_data,
    1194             :                      const char **r_algoname, int *r_npkey, int *r_nskey,
    1195             :                      const char **r_elems,
    1196             :                      gcry_mpi_t *array, int arraysize,
    1197             :                      gcry_sexp_t *r_curve, gcry_sexp_t *r_flags)
    1198             : {
    1199             :   gpg_error_t err;
    1200             :   gcry_sexp_t list, l2;
    1201             :   char *name;
    1202             :   const char *algoname, *format;
    1203             :   int npkey, nskey;
    1204          13 :   gcry_sexp_t curve = NULL;
    1205          13 :   gcry_sexp_t flags = NULL;
    1206             : 
    1207          13 :   *r_curve = NULL;
    1208          13 :   *r_flags = NULL;
    1209             : 
    1210          13 :   if (!req_private_key_data)
    1211             :     {
    1212          11 :       list = gcry_sexp_find_token (s_key, "shadowed-private-key", 0 );
    1213          11 :       if (!list)
    1214          11 :         list = gcry_sexp_find_token (s_key, "protected-private-key", 0 );
    1215          11 :       if (!list)
    1216           0 :         list = gcry_sexp_find_token (s_key, "private-key", 0 );
    1217             :     }
    1218             :   else
    1219           2 :     list = gcry_sexp_find_token (s_key, "private-key", 0);
    1220             : 
    1221          13 :   if (!list)
    1222             :     {
    1223           0 :       log_error ("invalid private key format\n");
    1224           0 :       return gpg_error (GPG_ERR_BAD_SECKEY);
    1225             :     }
    1226             : 
    1227          13 :   l2 = gcry_sexp_cadr (list);
    1228          13 :   gcry_sexp_release (list);
    1229          13 :   list = l2;
    1230          13 :   name = gcry_sexp_nth_string (list, 0);
    1231          13 :   if (!name)
    1232             :     {
    1233           0 :       gcry_sexp_release (list);
    1234           0 :       return gpg_error (GPG_ERR_INV_OBJ); /* Invalid structure of object. */
    1235             :     }
    1236             : 
    1237          13 :   if (arraysize < 7)
    1238           0 :     BUG ();
    1239             : 
    1240             :   /* Map NAME to a name as used by Libgcrypt.  We do not use the
    1241             :      Libgcrypt function here because we need a lowercase name and
    1242             :      require special treatment for some algorithms.  */
    1243          13 :   strlwr (name);
    1244          13 :   if (!strcmp (name, "rsa"))
    1245             :     {
    1246           4 :       algoname = "rsa";
    1247           4 :       format = "ned?p?q?u?";
    1248           4 :       npkey = 2;
    1249           4 :       nskey = 6;
    1250           4 :       err = gcry_sexp_extract_param (list, NULL, format,
    1251             :                                      array+0, array+1, array+2, array+3,
    1252             :                                      array+4, array+5, NULL);
    1253             :     }
    1254           9 :   else if (!strcmp (name, "elg"))
    1255             :     {
    1256           1 :       algoname = "elg";
    1257           1 :       format = "pgyx?";
    1258           1 :       npkey = 3;
    1259           1 :       nskey = 4;
    1260           1 :       err = gcry_sexp_extract_param (list, NULL, format,
    1261             :                                      array+0, array+1, array+2, array+3,
    1262             :                                      NULL);
    1263             :     }
    1264           8 :   else if (!strcmp (name, "dsa"))
    1265             :     {
    1266           5 :       algoname = "dsa";
    1267           5 :       format = "pqgyx?";
    1268           5 :       npkey = 4;
    1269           5 :       nskey = 5;
    1270           5 :       err = gcry_sexp_extract_param (list, NULL, format,
    1271             :                                      array+0, array+1, array+2, array+3,
    1272             :                                      array+4, NULL);
    1273             :     }
    1274           3 :   else if (!strcmp (name, "ecc") || !strcmp (name, "ecdsa"))
    1275             :     {
    1276           3 :       algoname = "ecc";
    1277           3 :       format = "qd?";
    1278           3 :       npkey = 1;
    1279           3 :       nskey = 2;
    1280           3 :       curve = gcry_sexp_find_token (list, "curve", 0);
    1281           3 :       flags = gcry_sexp_find_token (list, "flags", 0);
    1282           3 :       err = gcry_sexp_extract_param (list, NULL, format,
    1283             :                                      array+0, array+1, NULL);
    1284             :     }
    1285             :   else
    1286             :     {
    1287           0 :       err = gpg_error (GPG_ERR_PUBKEY_ALGO);
    1288             :     }
    1289          13 :   xfree (name);
    1290          13 :   gcry_sexp_release (list);
    1291          13 :   if (err)
    1292             :     {
    1293           0 :       gcry_sexp_release (curve);
    1294           0 :       gcry_sexp_release (flags);
    1295           0 :       return err;
    1296             :     }
    1297             :   else
    1298             :     {
    1299          13 :       *r_algoname = algoname;
    1300          13 :       if (r_elems)
    1301          11 :         *r_elems = format;
    1302          13 :       *r_npkey = npkey;
    1303          13 :       if (r_nskey)
    1304           2 :         *r_nskey = nskey;
    1305          13 :       *r_curve = curve;
    1306          13 :       *r_flags = flags;
    1307             : 
    1308          13 :       return 0;
    1309             :     }
    1310             : }
    1311             : 
    1312             : /* Convert our key S_KEY into an OpenPGP key transfer format.  On
    1313             :    success a canonical encoded S-expression is stored at R_TRANSFERKEY
    1314             :    and its length at R_TRANSFERKEYLEN; this S-expression is also
    1315             :    padded to a multiple of 64 bits.  */
    1316             : gpg_error_t
    1317           2 : convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase,
    1318             :                     unsigned char **r_transferkey, size_t *r_transferkeylen)
    1319             : {
    1320             :   gpg_error_t err;
    1321             :   const char *algoname;
    1322             :   int npkey, nskey;
    1323             :   gcry_mpi_t array[10];
    1324           2 :   gcry_sexp_t curve = NULL;
    1325           2 :   gcry_sexp_t flags = NULL;
    1326             :   char protect_iv[16];
    1327             :   char salt[8];
    1328             :   unsigned long s2k_count;
    1329             :   int i, j;
    1330             : 
    1331             :   (void)ctrl;
    1332             : 
    1333           2 :   *r_transferkey = NULL;
    1334             : 
    1335          22 :   for (i=0; i < DIM (array); i++)
    1336          20 :     array[i] = NULL;
    1337             : 
    1338           2 :   err = extract_private_key (s_key, 1, &algoname, &npkey, &nskey, NULL,
    1339             :                              array, DIM (array), &curve, &flags);
    1340           2 :   if (err)
    1341           0 :     return err;
    1342             : 
    1343           2 :   gcry_create_nonce (protect_iv, sizeof protect_iv);
    1344           2 :   gcry_create_nonce (salt, sizeof salt);
    1345             :   /* We need to use the encoded S2k count.  It is not possible to
    1346             :      encode it after it has been used because the encoding procedure
    1347             :      may round the value up.  */
    1348           2 :   s2k_count = get_standard_s2k_count_rfc4880 ();
    1349           2 :   err = apply_protection (array, npkey, nskey, passphrase,
    1350             :                           GCRY_CIPHER_AES, protect_iv, sizeof protect_iv,
    1351             :                           3, GCRY_MD_SHA1, salt, s2k_count);
    1352             :   /* Turn it into the transfer key S-expression.  Note that we always
    1353             :      return a protected key.  */
    1354           2 :   if (!err)
    1355             :     {
    1356             :       char countbuf[35];
    1357             :       membuf_t mbuf;
    1358             :       void *format_args[10+2];
    1359             :       gcry_sexp_t tmpkey;
    1360           2 :       gcry_sexp_t tmpsexp = NULL;
    1361             : 
    1362           2 :       snprintf (countbuf, sizeof countbuf, "%lu", s2k_count);
    1363             : 
    1364           2 :       init_membuf (&mbuf, 50);
    1365           2 :       put_membuf_str (&mbuf, "(skey");
    1366           9 :       for (i=j=0; i < npkey; i++)
    1367             :         {
    1368           7 :           put_membuf_str (&mbuf, " _ %m");
    1369           7 :           format_args[j++] = array + i;
    1370             :         }
    1371           2 :       put_membuf_str (&mbuf, " e %m");
    1372           2 :       format_args[j++] = array + npkey;
    1373           2 :       put_membuf_str (&mbuf, ")\n");
    1374           2 :       put_membuf (&mbuf, "", 1);
    1375             : 
    1376           2 :       tmpkey = NULL;
    1377             :       {
    1378           2 :         char *format = get_membuf (&mbuf, NULL);
    1379           2 :         if (!format)
    1380           0 :           err = gpg_error_from_syserror ();
    1381             :         else
    1382           2 :           err = gcry_sexp_build_array (&tmpkey, NULL, format, format_args);
    1383           2 :         xfree (format);
    1384             :       }
    1385           2 :       if (!err)
    1386           2 :         err = gcry_sexp_build (&tmpsexp, NULL,
    1387             :                                "(openpgp-private-key\n"
    1388             :                                " (version 1:4)\n"
    1389             :                                " (algo %s)\n"
    1390             :                                " %S%S\n"
    1391             :                                " (protection sha1 aes %b 1:3 sha1 %b %s))\n",
    1392             :                                algoname,
    1393             :                                curve,
    1394             :                                tmpkey,
    1395             :                                (int)sizeof protect_iv, protect_iv,
    1396             :                                (int)sizeof salt, salt,
    1397             :                                countbuf);
    1398           2 :       gcry_sexp_release (tmpkey);
    1399           2 :       if (!err)
    1400           2 :         err = make_canon_sexp_pad (tmpsexp, 0, r_transferkey, r_transferkeylen);
    1401           2 :       gcry_sexp_release (tmpsexp);
    1402             :     }
    1403             : 
    1404          22 :   for (i=0; i < DIM (array); i++)
    1405          20 :     gcry_mpi_release (array[i]);
    1406           2 :   gcry_sexp_release (curve);
    1407           2 :   gcry_sexp_release (flags);
    1408             : 
    1409           2 :   return err;
    1410             : }

Generated by: LCOV version 1.11