LCOV - code coverage report
Current view: top level - g10 - export.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 375 1050 35.7 %
Date: 2016-09-12 12:29:17 Functions: 14 29 48.3 %

          Line data    Source code
       1             : /* export.c - Export keys in the OpenPGP defined format.
       2             :  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
       3             :  *               2005, 2010 Free Software Foundation, Inc.
       4             :  * Copyright (C) 1998-2016  Werner Koch
       5             :  *
       6             :  * This file is part of GnuPG.
       7             :  *
       8             :  * GnuPG is free software; you can redistribute it and/or modify
       9             :  * it under the terms of the GNU General Public License as published by
      10             :  * the Free Software Foundation; either version 3 of the License, or
      11             :  * (at your option) any later version.
      12             :  *
      13             :  * GnuPG is distributed in the hope that it will be useful,
      14             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :  * GNU General Public License for more details.
      17             :  *
      18             :  * You should have received a copy of the GNU General Public License
      19             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      20             :  */
      21             : 
      22             : #include <config.h>
      23             : #include <stdio.h>
      24             : #include <stdlib.h>
      25             : #include <string.h>
      26             : #include <errno.h>
      27             : 
      28             : #include "gpg.h"
      29             : #include "options.h"
      30             : #include "packet.h"
      31             : #include "status.h"
      32             : #include "keydb.h"
      33             : #include "util.h"
      34             : #include "main.h"
      35             : #include "i18n.h"
      36             : #include "membuf.h"
      37             : #include "host2net.h"
      38             : #include "zb32.h"
      39             : #include "recsel.h"
      40             : #include "mbox-util.h"
      41             : #include "init.h"
      42             : #include "trustdb.h"
      43             : #include "call-agent.h"
      44             : 
      45             : /* An object to keep track of subkeys. */
      46             : struct subkey_list_s
      47             : {
      48             :   struct subkey_list_s *next;
      49             :   u32 kid[2];
      50             : };
      51             : typedef struct subkey_list_s *subkey_list_t;
      52             : 
      53             : 
      54             : /* An object to track statistics for export operations.  */
      55             : struct export_stats_s
      56             : {
      57             :   ulong count;            /* Number of processed keys.        */
      58             :   ulong secret_count;     /* Number of secret keys seen.      */
      59             :   ulong exported;         /* Number of actual exported keys.  */
      60             : };
      61             : 
      62             : 
      63             : /* A global variable to store the selector created from
      64             :  * --export-filter keep-uid=EXPR.
      65             :  * --export-filter drop-subkey=EXPR.
      66             :  *
      67             :  * FIXME: We should put this into the CTRL object but that requires a
      68             :  * lot more changes right now.
      69             :  */
      70             : static recsel_expr_t export_keep_uid;
      71             : static recsel_expr_t export_drop_subkey;
      72             : 
      73             : 
      74             : 
      75             : /* Local prototypes.  */
      76             : static int do_export (ctrl_t ctrl, strlist_t users, int secret,
      77             :                       unsigned int options, export_stats_t stats);
      78             : static int do_export_stream (ctrl_t ctrl, iobuf_t out,
      79             :                              strlist_t users, int secret,
      80             :                              kbnode_t *keyblock_out, unsigned int options,
      81             :                              export_stats_t stats, int *any);
      82             : static gpg_error_t print_pka_or_dane_records
      83             : /**/                 (iobuf_t out, kbnode_t keyblock, PKT_public_key *pk,
      84             :                       const void *data, size_t datalen,
      85             :                       int print_pka, int print_dane);
      86             : 
      87             : 
      88             : static void
      89           0 : cleanup_export_globals (void)
      90             : {
      91           0 :   recsel_release (export_keep_uid);
      92           0 :   export_keep_uid = NULL;
      93           0 :   recsel_release (export_drop_subkey);
      94           0 :   export_drop_subkey = NULL;
      95           0 : }
      96             : 
      97             : 
      98             : /* Option parser for export options.  See parse_options fro
      99             :    details.  */
     100             : int
     101           0 : parse_export_options(char *str,unsigned int *options,int noisy)
     102             : {
     103           0 :   struct parse_options export_opts[]=
     104             :     {
     105             :       {"export-local-sigs",EXPORT_LOCAL_SIGS,NULL,
     106             :        N_("export signatures that are marked as local-only")},
     107             :       {"export-attributes",EXPORT_ATTRIBUTES,NULL,
     108             :        N_("export attribute user IDs (generally photo IDs)")},
     109             :       {"export-sensitive-revkeys",EXPORT_SENSITIVE_REVKEYS,NULL,
     110             :        N_("export revocation keys marked as \"sensitive\"")},
     111             :       {"export-clean",EXPORT_CLEAN,NULL,
     112             :        N_("remove unusable parts from key during export")},
     113             :       {"export-minimal",EXPORT_MINIMAL|EXPORT_CLEAN,NULL,
     114             :        N_("remove as much as possible from key during export")},
     115             : 
     116             :       {"export-pka", EXPORT_PKA_FORMAT, NULL, NULL },
     117             :       {"export-dane", EXPORT_DANE_FORMAT, NULL, NULL },
     118             : 
     119             :       /* Aliases for backward compatibility */
     120             :       {"include-local-sigs",EXPORT_LOCAL_SIGS,NULL,NULL},
     121             :       {"include-attributes",EXPORT_ATTRIBUTES,NULL,NULL},
     122             :       {"include-sensitive-revkeys",EXPORT_SENSITIVE_REVKEYS,NULL,NULL},
     123             :       /* dummy */
     124             :       {"export-unusable-sigs",0,NULL,NULL},
     125             :       {"export-clean-sigs",0,NULL,NULL},
     126             :       {"export-clean-uids",0,NULL,NULL},
     127             :       {NULL,0,NULL,NULL}
     128             :       /* add tags for include revoked and disabled? */
     129             :     };
     130             : 
     131           0 :   return parse_options(str,options,export_opts,noisy);
     132             : }
     133             : 
     134             : 
     135             : /* Parse and set an export filter from string.  STRING has the format
     136             :  * "NAME=EXPR" with NAME being the name of the filter.  Spaces before
     137             :  * and after NAME are not allowed.  If this function is called several
     138             :  * times all expressions for the same NAME are concatenated.
     139             :  * Supported filter names are:
     140             :  *
     141             :  *  - keep-uid :: If the expression evaluates to true for a certain
     142             :  *                user ID packet, that packet and all it dependencies
     143             :  *                will be exported.  The expression may use these
     144             :  *                variables:
     145             :  *
     146             :  *                - uid  :: The entire user ID.
     147             :  *                - mbox :: The mail box part of the user ID.
     148             :  *                - primary :: Evaluate to true for the primary user ID.
     149             :  *
     150             :  *  - drop-subkey :: If the expression evaluates to true for a subkey
     151             :  *                packet that subkey and all it dependencies will be
     152             :  *                remove from the keyblock.  The expression may use these
     153             :  *                variables:
     154             :  *
     155             :  *                - secret   :: 1 for a secret subkey, else 0.
     156             :  *                - key_algo :: Public key algorithm id
     157             :  */
     158             : gpg_error_t
     159           0 : parse_and_set_export_filter (const char *string)
     160             : {
     161             :   gpg_error_t err;
     162             : 
     163             :   /* Auto register the cleanup function.  */
     164           0 :   register_mem_cleanup_func (cleanup_export_globals);
     165             : 
     166           0 :   if (!strncmp (string, "keep-uid=", 9))
     167           0 :     err = recsel_parse_expr (&export_keep_uid, string+9);
     168           0 :   else if (!strncmp (string, "drop-subkey=", 12))
     169           0 :     err = recsel_parse_expr (&export_drop_subkey, string+12);
     170             :   else
     171           0 :     err = gpg_error (GPG_ERR_INV_NAME);
     172             : 
     173           0 :   return err;
     174             : }
     175             : 
     176             : 
     177             : /* Create a new export stats object initialized to zero.  On error
     178             :    returns NULL and sets ERRNO.  */
     179             : export_stats_t
     180           7 : export_new_stats (void)
     181             : {
     182             :   export_stats_t stats;
     183             : 
     184           7 :   return xtrycalloc (1, sizeof *stats);
     185             : }
     186             : 
     187             : 
     188             : /* Release an export stats object.  */
     189             : void
     190           7 : export_release_stats (export_stats_t stats)
     191             : {
     192           7 :   xfree (stats);
     193           7 : }
     194             : 
     195             : 
     196             : /* Print export statistics using the status interface.  */
     197             : void
     198           7 : export_print_stats (export_stats_t stats)
     199             : {
     200           7 :   if (!stats)
     201           7 :     return;
     202             : 
     203           7 :   if (is_status_enabled ())
     204             :     {
     205             :       char buf[15*20];
     206             : 
     207           0 :       snprintf (buf, sizeof buf, "%lu %lu %lu",
     208             :                 stats->count,
     209             :                 stats->secret_count,
     210             :                 stats->exported );
     211           0 :       write_status_text (STATUS_EXPORT_RES, buf);
     212             :     }
     213             : }
     214             : 
     215             : 
     216             : /*
     217             :  * Export public keys (to stdout or to --output FILE).
     218             :  *
     219             :  * Depending on opt.armor the output is armored.  OPTIONS are defined
     220             :  * in main.h.  If USERS is NULL, all keys will be exported.  STATS is
     221             :  * either an export stats object for update or NULL.
     222             :  *
     223             :  * This function is the core of "gpg --export".
     224             :  */
     225             : int
     226           4 : export_pubkeys (ctrl_t ctrl, strlist_t users, unsigned int options,
     227             :                 export_stats_t stats)
     228             : {
     229           4 :   return do_export (ctrl, users, 0, options, stats);
     230             : }
     231             : 
     232             : 
     233             : /*
     234             :  * Export secret keys (to stdout or to --output FILE).
     235             :  *
     236             :  * Depending on opt.armor the output is armored.  If USERS is NULL,
     237             :  * all secret keys will be exported.  STATS is either an export stats
     238             :  * object for update or NULL.
     239             :  *
     240             :  * This function is the core of "gpg --export-secret-keys".
     241             :  */
     242             : int
     243           3 : export_seckeys (ctrl_t ctrl, strlist_t users, export_stats_t stats)
     244             : {
     245           3 :   return do_export (ctrl, users, 1, 0, stats);
     246             : }
     247             : 
     248             : 
     249             : /*
     250             :  * Export secret sub keys (to stdout or to --output FILE).
     251             :  *
     252             :  * This is the same as export_seckeys but replaces the primary key by
     253             :  * a stub key.  Depending on opt.armor the output is armored.  If
     254             :  * USERS is NULL, all secret subkeys will be exported.  STATS is
     255             :  * either an export stats object for update or NULL.
     256             :  *
     257             :  * This function is the core of "gpg --export-secret-subkeys".
     258             :  */
     259             : int
     260           0 : export_secsubkeys (ctrl_t ctrl, strlist_t users, export_stats_t stats)
     261             : {
     262           0 :   return do_export (ctrl, users, 2, 0, stats);
     263             : }
     264             : 
     265             : 
     266             : /*
     267             :  * Export a single key into a memory buffer.  STATS is either an
     268             :  * export stats object for update or NULL.
     269             :  */
     270             : gpg_error_t
     271           0 : export_pubkey_buffer (ctrl_t ctrl, const char *keyspec, unsigned int options,
     272             :                       export_stats_t stats,
     273             :                       kbnode_t *r_keyblock, void **r_data, size_t *r_datalen)
     274             : {
     275             :   gpg_error_t err;
     276             :   iobuf_t iobuf;
     277             :   int any;
     278             :   strlist_t helplist;
     279             : 
     280           0 :   *r_keyblock = NULL;
     281           0 :   *r_data = NULL;
     282           0 :   *r_datalen = 0;
     283             : 
     284           0 :   helplist = NULL;
     285           0 :   if (!add_to_strlist_try (&helplist, keyspec))
     286           0 :     return gpg_error_from_syserror ();
     287             : 
     288           0 :   iobuf = iobuf_temp ();
     289           0 :   err = do_export_stream (ctrl, iobuf, helplist, 0, r_keyblock, options,
     290             :                           stats, &any);
     291           0 :   if (!err && !any)
     292           0 :     err = gpg_error (GPG_ERR_NOT_FOUND);
     293           0 :   if (!err)
     294             :     {
     295             :       const void *src;
     296             :       size_t datalen;
     297             : 
     298           0 :       iobuf_flush_temp (iobuf);
     299           0 :       src = iobuf_get_temp_buffer (iobuf);
     300           0 :       datalen = iobuf_get_temp_length (iobuf);
     301           0 :       if (!datalen)
     302           0 :         err = gpg_error (GPG_ERR_NO_PUBKEY);
     303           0 :       else if (!(*r_data = xtrymalloc (datalen)))
     304           0 :         err = gpg_error_from_syserror ();
     305             :       else
     306             :         {
     307           0 :           memcpy (*r_data, src, datalen);
     308           0 :           *r_datalen = datalen;
     309             :         }
     310             :     }
     311           0 :   iobuf_close (iobuf);
     312           0 :   free_strlist (helplist);
     313           0 :   if (err && *r_keyblock)
     314             :     {
     315           0 :       release_kbnode (*r_keyblock);
     316           0 :       *r_keyblock = NULL;
     317             :     }
     318           0 :   return err;
     319             : }
     320             : 
     321             : 
     322             : /* Export the keys identified by the list of strings in USERS.  If
     323             :    Secret is false public keys will be exported.  With secret true
     324             :    secret keys will be exported; in this case 1 means the entire
     325             :    secret keyblock and 2 only the subkeys.  OPTIONS are the export
     326             :    options to apply.  */
     327             : static int
     328           7 : do_export (ctrl_t ctrl, strlist_t users, int secret, unsigned int options,
     329             :            export_stats_t stats)
     330             : {
     331           7 :   IOBUF out = NULL;
     332             :   int any, rc;
     333           7 :   armor_filter_context_t *afx = NULL;
     334             :   compress_filter_context_t zfx;
     335             : 
     336           7 :   memset( &zfx, 0, sizeof zfx);
     337             : 
     338           7 :   rc = open_outfile (-1, NULL, 0, !!secret, &out );
     339           7 :   if (rc)
     340           0 :     return rc;
     341             : 
     342           7 :   if ( opt.armor && !(options & (EXPORT_PKA_FORMAT|EXPORT_DANE_FORMAT)) )
     343             :     {
     344           0 :       afx = new_armor_context ();
     345           0 :       afx->what = secret? 5 : 1;
     346           0 :       push_armor_filter (afx, out);
     347             :     }
     348             : 
     349           7 :   rc = do_export_stream (ctrl, out, users, secret, NULL, options, stats, &any);
     350             : 
     351           7 :   if ( rc || !any )
     352           0 :     iobuf_cancel (out);
     353             :   else
     354           7 :     iobuf_close (out);
     355           7 :   release_armor_context (afx);
     356           7 :   return rc;
     357             : }
     358             : 
     359             : 
     360             : 
     361             : /* Release an entire subkey list. */
     362             : static void
     363           7 : release_subkey_list (subkey_list_t list)
     364             : {
     365          14 :   while (list)
     366             :     {
     367           0 :       subkey_list_t tmp = list->next;;
     368           0 :       xfree (list);
     369           0 :       list = tmp;
     370             :     }
     371           7 : }
     372             : 
     373             : 
     374             : /* Returns true if NODE is a subkey and contained in LIST. */
     375             : static int
     376           0 : subkey_in_list_p (subkey_list_t list, KBNODE node)
     377             : {
     378           0 :   if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
     379           0 :       || node->pkt->pkttype == PKT_SECRET_SUBKEY )
     380             :     {
     381             :       u32 kid[2];
     382             : 
     383           0 :       keyid_from_pk (node->pkt->pkt.public_key, kid);
     384             : 
     385           0 :       for (; list; list = list->next)
     386           0 :         if (list->kid[0] == kid[0] && list->kid[1] == kid[1])
     387           0 :           return 1;
     388             :     }
     389           0 :   return 0;
     390             : }
     391             : 
     392             : /* Allocate a new subkey list item from NODE. */
     393             : static subkey_list_t
     394           0 : new_subkey_list_item (KBNODE node)
     395             : {
     396           0 :   subkey_list_t list = xcalloc (1, sizeof *list);
     397             : 
     398           0 :   if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
     399           0 :       || node->pkt->pkttype == PKT_SECRET_SUBKEY)
     400           0 :     keyid_from_pk (node->pkt->pkt.public_key, list->kid);
     401             : 
     402           0 :   return list;
     403             : }
     404             : 
     405             : 
     406             : /* Helper function to check whether the subkey at NODE actually
     407             :    matches the description at DESC.  The function returns true if the
     408             :    key under question has been specified by an exact specification
     409             :    (keyID or fingerprint) and does match the one at NODE.  It is
     410             :    assumed that the packet at NODE is either a public or secret
     411             :    subkey. */
     412             : static int
     413           0 : exact_subkey_match_p (KEYDB_SEARCH_DESC *desc, KBNODE node)
     414             : {
     415             :   u32 kid[2];
     416             :   byte fpr[MAX_FINGERPRINT_LEN];
     417             :   size_t fprlen;
     418           0 :   int result = 0;
     419             : 
     420           0 :   switch(desc->mode)
     421             :     {
     422             :     case KEYDB_SEARCH_MODE_SHORT_KID:
     423             :     case KEYDB_SEARCH_MODE_LONG_KID:
     424           0 :       keyid_from_pk (node->pkt->pkt.public_key, kid);
     425           0 :       break;
     426             : 
     427             :     case KEYDB_SEARCH_MODE_FPR16:
     428             :     case KEYDB_SEARCH_MODE_FPR20:
     429             :     case KEYDB_SEARCH_MODE_FPR:
     430           0 :       fingerprint_from_pk (node->pkt->pkt.public_key, fpr,&fprlen);
     431           0 :       break;
     432             : 
     433             :     default:
     434           0 :       break;
     435             :     }
     436             : 
     437           0 :   switch(desc->mode)
     438             :     {
     439             :     case KEYDB_SEARCH_MODE_SHORT_KID:
     440           0 :       if (desc->u.kid[1] == kid[1])
     441           0 :         result = 1;
     442           0 :       break;
     443             : 
     444             :     case KEYDB_SEARCH_MODE_LONG_KID:
     445           0 :       if (desc->u.kid[0] == kid[0] && desc->u.kid[1] == kid[1])
     446           0 :         result = 1;
     447           0 :       break;
     448             : 
     449             :     case KEYDB_SEARCH_MODE_FPR16:
     450           0 :       if (!memcmp (desc->u.fpr, fpr, 16))
     451           0 :         result = 1;
     452           0 :       break;
     453             : 
     454             :     case KEYDB_SEARCH_MODE_FPR20:
     455             :     case KEYDB_SEARCH_MODE_FPR:
     456           0 :       if (!memcmp (desc->u.fpr, fpr, 20))
     457           0 :         result = 1;
     458           0 :       break;
     459             : 
     460             :     default:
     461           0 :       break;
     462             :     }
     463             : 
     464           0 :   return result;
     465             : }
     466             : 
     467             : 
     468             : /* Return an error if the key represented by the S-expression S_KEY
     469             :  * and the OpenPGP key represented by PK do not use the same curve. */
     470             : static gpg_error_t
     471           0 : match_curve_skey_pk (gcry_sexp_t s_key, PKT_public_key *pk)
     472             : {
     473           0 :   gcry_sexp_t curve = NULL;
     474           0 :   gcry_sexp_t flags = NULL;
     475           0 :   char *curve_str = NULL;
     476             :   char *flag;
     477           0 :   const char *oidstr = NULL;
     478           0 :   gcry_mpi_t curve_as_mpi = NULL;
     479             :   gpg_error_t err;
     480           0 :   int is_eddsa = 0;
     481           0 :   int idx = 0;
     482             : 
     483           0 :   if (!(pk->pubkey_algo==PUBKEY_ALGO_ECDH
     484           0 :         || pk->pubkey_algo==PUBKEY_ALGO_ECDSA
     485           0 :         || pk->pubkey_algo==PUBKEY_ALGO_EDDSA))
     486           0 :     return gpg_error (GPG_ERR_PUBKEY_ALGO);
     487             : 
     488           0 :   curve = gcry_sexp_find_token (s_key, "curve", 0);
     489           0 :   if (!curve)
     490             :     {
     491           0 :       log_error ("no reported curve\n");
     492           0 :       return gpg_error (GPG_ERR_UNKNOWN_CURVE);
     493             :     }
     494           0 :   curve_str = gcry_sexp_nth_string (curve, 1);
     495           0 :   gcry_sexp_release (curve); curve = NULL;
     496           0 :   if (!curve_str)
     497             :     {
     498           0 :       log_error ("no curve name\n");
     499           0 :       return gpg_error (GPG_ERR_UNKNOWN_CURVE);
     500             :     }
     501           0 :   oidstr = openpgp_curve_to_oid (curve_str, NULL);
     502           0 :   if (!oidstr)
     503             :     {
     504           0 :       log_error ("no OID known for curve '%s'\n", curve_str);
     505           0 :       xfree (curve_str);
     506           0 :       return gpg_error (GPG_ERR_UNKNOWN_CURVE);
     507             :     }
     508           0 :   xfree (curve_str);
     509           0 :   err = openpgp_oid_from_str (oidstr, &curve_as_mpi);
     510           0 :   if (err)
     511           0 :     return err;
     512           0 :   if (gcry_mpi_cmp (pk->pkey[0], curve_as_mpi))
     513             :     {
     514           0 :       log_error ("curves do not match\n");
     515           0 :       gcry_mpi_release (curve_as_mpi);
     516           0 :       return gpg_error (GPG_ERR_INV_CURVE);
     517             :     }
     518           0 :   gcry_mpi_release (curve_as_mpi);
     519           0 :   flags = gcry_sexp_find_token (s_key, "flags", 0);
     520           0 :   if (flags)
     521             :     {
     522           0 :       for (idx = 1; idx < gcry_sexp_length (flags); idx++)
     523             :         {
     524           0 :           flag = gcry_sexp_nth_string (flags, idx);
     525           0 :           if (flag && (strcmp ("eddsa", flag) == 0))
     526           0 :             is_eddsa = 1;
     527           0 :           gcry_free (flag);
     528             :         }
     529             :     }
     530           0 :   if (is_eddsa != (pk->pubkey_algo == PUBKEY_ALGO_EDDSA))
     531             :     {
     532           0 :       log_error ("disagreement about EdDSA\n");
     533           0 :       err = gpg_error (GPG_ERR_INV_CURVE);
     534             :     }
     535             : 
     536           0 :   return err;
     537             : }
     538             : 
     539             : 
     540             : /* Return a canonicalized public key algoithms.  This is used to
     541             :    compare different flavors of algorithms (e.g. ELG and ELG_E are
     542             :    considered the same).  */
     543             : static enum gcry_pk_algos
     544           7 : canon_pk_algo (enum gcry_pk_algos algo)
     545             : {
     546           7 :   switch (algo)
     547             :     {
     548             :     case GCRY_PK_RSA:
     549             :     case GCRY_PK_RSA_E:
     550           1 :     case GCRY_PK_RSA_S: return GCRY_PK_RSA;
     551             :     case GCRY_PK_ELG:
     552           3 :     case GCRY_PK_ELG_E: return GCRY_PK_ELG;
     553             :     case GCRY_PK_ECC:
     554             :     case GCRY_PK_ECDSA:
     555           0 :     case GCRY_PK_ECDH: return GCRY_PK_ECC;
     556           3 :     default: return algo;
     557             :     }
     558             : }
     559             : 
     560             : 
     561             : /* Take a cleartext dump of a secret key in PK and change the
     562             :  * parameter array in PK to include the secret parameters.  */
     563             : static gpg_error_t
     564           3 : cleartext_secret_key_to_openpgp (gcry_sexp_t s_key, PKT_public_key *pk)
     565             : {
     566           3 :   gpg_error_t err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
     567             :   gcry_sexp_t top_list;
     568           3 :   gcry_sexp_t key = NULL;
     569           3 :   char *key_type = NULL;
     570             :   enum gcry_pk_algos pk_algo;
     571             :   struct seckey_info *ski;
     572             :   int idx, sec_start;
     573           3 :   gcry_mpi_t pub_params[10] = { NULL };
     574             : 
     575             :   /* we look for a private-key, then the first element in it tells us
     576             :      the type */
     577           3 :   top_list = gcry_sexp_find_token (s_key, "private-key", 0);
     578           3 :   if (!top_list)
     579           0 :     goto bad_seckey;
     580           3 :   if (gcry_sexp_length(top_list) != 2)
     581           0 :     goto bad_seckey;
     582           3 :   key = gcry_sexp_nth (top_list, 1);
     583           3 :   if (!key)
     584           0 :     goto bad_seckey;
     585           3 :   key_type = gcry_sexp_nth_string(key, 0);
     586           3 :   pk_algo = gcry_pk_map_name (key_type);
     587             : 
     588           3 :   log_assert (!pk->seckey_info);
     589             : 
     590           3 :   pk->seckey_info = ski = xtrycalloc (1, sizeof *ski);
     591           3 :   if (!ski)
     592             :     {
     593           0 :       err = gpg_error_from_syserror ();
     594           0 :       goto leave;
     595             :     }
     596             : 
     597           3 :   switch (canon_pk_algo (pk_algo))
     598             :     {
     599             :     case GCRY_PK_RSA:
     600           1 :       if (!is_RSA (pk->pubkey_algo))
     601           0 :         goto bad_pubkey_algo;
     602           1 :       err = gcry_sexp_extract_param (key, NULL, "ne",
     603             :                                      &pub_params[0],
     604             :                                      &pub_params[1],
     605             :                                      NULL);
     606           3 :       for (idx=0; idx < 2 && !err; idx++)
     607           2 :         if (gcry_mpi_cmp(pk->pkey[idx], pub_params[idx]))
     608           0 :           err = gpg_error (GPG_ERR_BAD_PUBKEY);
     609           1 :       if (!err)
     610             :         {
     611           5 :           for (idx = 2; idx < 6 && !err; idx++)
     612             :             {
     613           4 :               gcry_mpi_release (pk->pkey[idx]);
     614           4 :               pk->pkey[idx] = NULL;
     615             :             }
     616           1 :           err = gcry_sexp_extract_param (key, NULL, "dpqu",
     617             :                                          &pk->pkey[2],
     618             :                                          &pk->pkey[3],
     619             :                                          &pk->pkey[4],
     620             :                                          &pk->pkey[5],
     621             :                                          NULL);
     622             :         }
     623           1 :       if (!err)
     624             :         {
     625           5 :           for (idx = 2; idx < 6; idx++)
     626           4 :             ski->csum += checksum_mpi (pk->pkey[idx]);
     627             :         }
     628           1 :       break;
     629             : 
     630             :     case GCRY_PK_DSA:
     631           1 :       if (!is_DSA (pk->pubkey_algo))
     632           0 :         goto bad_pubkey_algo;
     633           1 :       err = gcry_sexp_extract_param (key, NULL, "pqgy",
     634             :                                      &pub_params[0],
     635             :                                      &pub_params[1],
     636             :                                      &pub_params[2],
     637             :                                      &pub_params[3],
     638             :                                      NULL);
     639           5 :       for (idx=0; idx < 4 && !err; idx++)
     640           4 :         if (gcry_mpi_cmp(pk->pkey[idx], pub_params[idx]))
     641           0 :           err = gpg_error (GPG_ERR_BAD_PUBKEY);
     642           1 :       if (!err)
     643             :         {
     644           1 :           gcry_mpi_release (pk->pkey[4]);
     645           1 :           pk->pkey[4] = NULL;
     646           1 :           err = gcry_sexp_extract_param (key, NULL, "x",
     647             :                                          &pk->pkey[4],
     648             :                                          NULL);
     649             :         }
     650           1 :       if (!err)
     651           1 :         ski->csum += checksum_mpi (pk->pkey[4]);
     652           1 :       break;
     653             : 
     654             :     case GCRY_PK_ELG:
     655           1 :       if (!is_ELGAMAL (pk->pubkey_algo))
     656           0 :         goto bad_pubkey_algo;
     657           1 :       err = gcry_sexp_extract_param (key, NULL, "pgy",
     658             :                                      &pub_params[0],
     659             :                                      &pub_params[1],
     660             :                                      &pub_params[2],
     661             :                                      NULL);
     662           4 :       for (idx=0; idx < 3 && !err; idx++)
     663           3 :         if (gcry_mpi_cmp(pk->pkey[idx], pub_params[idx]))
     664           0 :           err = gpg_error (GPG_ERR_BAD_PUBKEY);
     665           1 :       if (!err)
     666             :         {
     667           1 :           gcry_mpi_release (pk->pkey[3]);
     668           1 :           pk->pkey[3] = NULL;
     669           1 :           err = gcry_sexp_extract_param (key, NULL, "x",
     670             :                                          &pk->pkey[3],
     671             :                                          NULL);
     672             :         }
     673           1 :       if (!err)
     674           1 :         ski->csum += checksum_mpi (pk->pkey[3]);
     675           1 :       break;
     676             : 
     677             :     case GCRY_PK_ECC:
     678           0 :       err = match_curve_skey_pk (key, pk);
     679           0 :       if (err)
     680           0 :         goto leave;
     681           0 :       if (!err)
     682           0 :         err = gcry_sexp_extract_param (key, NULL, "q",
     683             :                                        &pub_params[0],
     684             :                                        NULL);
     685           0 :       if (!err && (gcry_mpi_cmp(pk->pkey[1], pub_params[0])))
     686           0 :         err = gpg_error (GPG_ERR_BAD_PUBKEY);
     687             : 
     688           0 :       sec_start = 2;
     689           0 :       if (pk->pubkey_algo == PUBKEY_ALGO_ECDH)
     690           0 :         sec_start += 1;
     691           0 :       if (!err)
     692             :         {
     693           0 :           gcry_mpi_release (pk->pkey[sec_start]);
     694           0 :           pk->pkey[sec_start] = NULL;
     695           0 :           err = gcry_sexp_extract_param (key, NULL, "d",
     696             :                                          &pk->pkey[sec_start],
     697             :                                          NULL);
     698             :         }
     699             : 
     700           0 :       if (!err)
     701           0 :         ski->csum += checksum_mpi (pk->pkey[sec_start]);
     702           0 :       break;
     703             : 
     704             :     default:
     705           0 :       pk->seckey_info = NULL;
     706           0 :       xfree (ski);
     707           0 :       err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
     708           0 :       break;
     709             :     }
     710             : 
     711             :  leave:
     712           3 :   gcry_sexp_release (top_list);
     713           3 :   gcry_sexp_release (key);
     714           3 :   gcry_free (key_type);
     715             : 
     716          33 :   for (idx=0; idx < DIM(pub_params); idx++)
     717          30 :     gcry_mpi_release (pub_params[idx]);
     718           6 :   return err;
     719             : 
     720             :  bad_pubkey_algo:
     721           0 :   err = gpg_error (GPG_ERR_PUBKEY_ALGO);
     722           0 :   goto leave;
     723             : 
     724             :  bad_seckey:
     725           0 :   err = gpg_error (GPG_ERR_BAD_SECKEY);
     726           0 :   goto leave;
     727             : }
     728             : 
     729             : 
     730             : /* Use the key transfer format given in S_PGP to create the secinfo
     731             :    structure in PK and change the parameter array in PK to include the
     732             :    secret parameters.  */
     733             : static gpg_error_t
     734           2 : transfer_format_to_openpgp (gcry_sexp_t s_pgp, PKT_public_key *pk)
     735             : {
     736             :   gpg_error_t err;
     737             :   gcry_sexp_t top_list;
     738           2 :   gcry_sexp_t list = NULL;
     739           2 :   char *curve = NULL;
     740             :   const char *value;
     741             :   size_t valuelen;
     742             :   char *string;
     743             :   int  idx;
     744             :   int  is_v4, is_protected;
     745             :   enum gcry_pk_algos pk_algo;
     746           2 :   int  protect_algo = 0;
     747             :   char iv[16];
     748           2 :   int  ivlen = 0;
     749           2 :   int  s2k_mode = 0;
     750           2 :   int  s2k_algo = 0;
     751             :   byte s2k_salt[8];
     752           2 :   u32  s2k_count = 0;
     753           2 :   int  is_ecdh = 0;
     754             :   size_t npkey, nskey;
     755             :   gcry_mpi_t skey[10];  /* We support up to 9 parameters.  */
     756           2 :   int skeyidx = 0;
     757             :   struct seckey_info *ski;
     758             : 
     759             :   /* gcry_log_debugsxp ("transferkey", s_pgp); */
     760           2 :   top_list = gcry_sexp_find_token (s_pgp, "openpgp-private-key", 0);
     761           2 :   if (!top_list)
     762           0 :     goto bad_seckey;
     763             : 
     764           2 :   list = gcry_sexp_find_token (top_list, "version", 0);
     765           2 :   if (!list)
     766           0 :     goto bad_seckey;
     767           2 :   value = gcry_sexp_nth_data (list, 1, &valuelen);
     768           2 :   if (!value || valuelen != 1 || !(value[0] == '3' || value[0] == '4'))
     769             :     goto bad_seckey;
     770           2 :   is_v4 = (value[0] == '4');
     771             : 
     772           2 :   gcry_sexp_release (list);
     773           2 :   list = gcry_sexp_find_token (top_list, "protection", 0);
     774           2 :   if (!list)
     775           0 :     goto bad_seckey;
     776           2 :   value = gcry_sexp_nth_data (list, 1, &valuelen);
     777           2 :   if (!value)
     778           0 :     goto bad_seckey;
     779           2 :   if (valuelen == 4 && !memcmp (value, "sha1", 4))
     780           2 :     is_protected = 2;
     781           0 :   else if (valuelen == 3 && !memcmp (value, "sum", 3))
     782           0 :     is_protected = 1;
     783           0 :   else if (valuelen == 4 && !memcmp (value, "none", 4))
     784           0 :     is_protected = 0;
     785             :   else
     786             :     goto bad_seckey;
     787           2 :   if (is_protected)
     788             :     {
     789           2 :       string = gcry_sexp_nth_string (list, 2);
     790           2 :       if (!string)
     791           0 :         goto bad_seckey;
     792           2 :       protect_algo = gcry_cipher_map_name (string);
     793           2 :       xfree (string);
     794             : 
     795           2 :       value = gcry_sexp_nth_data (list, 3, &valuelen);
     796           2 :       if (!value || !valuelen || valuelen > sizeof iv)
     797             :         goto bad_seckey;
     798           2 :       memcpy (iv, value, valuelen);
     799           2 :       ivlen = valuelen;
     800             : 
     801           2 :       string = gcry_sexp_nth_string (list, 4);
     802           2 :       if (!string)
     803           0 :         goto bad_seckey;
     804           2 :       s2k_mode = strtol (string, NULL, 10);
     805           2 :       xfree (string);
     806             : 
     807           2 :       string = gcry_sexp_nth_string (list, 5);
     808           2 :       if (!string)
     809           0 :         goto bad_seckey;
     810           2 :       s2k_algo = gcry_md_map_name (string);
     811           2 :       xfree (string);
     812             : 
     813           2 :       value = gcry_sexp_nth_data (list, 6, &valuelen);
     814           2 :       if (!value || !valuelen || valuelen > sizeof s2k_salt)
     815             :         goto bad_seckey;
     816           2 :       memcpy (s2k_salt, value, valuelen);
     817             : 
     818           2 :       string = gcry_sexp_nth_string (list, 7);
     819           2 :       if (!string)
     820           0 :         goto bad_seckey;
     821           2 :       s2k_count = strtoul (string, NULL, 10);
     822           2 :       xfree (string);
     823             :     }
     824             : 
     825             :   /* Parse the gcrypt PK algo and check that it is okay.  */
     826           2 :   gcry_sexp_release (list);
     827           2 :   list = gcry_sexp_find_token (top_list, "algo", 0);
     828           2 :   if (!list)
     829           0 :     goto bad_seckey;
     830           2 :   string = gcry_sexp_nth_string (list, 1);
     831           2 :   if (!string)
     832           0 :     goto bad_seckey;
     833           2 :   pk_algo = gcry_pk_map_name (string);
     834           2 :   xfree (string); string = NULL;
     835           2 :   if (gcry_pk_algo_info (pk_algo, GCRYCTL_GET_ALGO_NPKEY, NULL, &npkey)
     836           2 :       || gcry_pk_algo_info (pk_algo, GCRYCTL_GET_ALGO_NSKEY, NULL, &nskey)
     837           2 :       || !npkey || npkey >= nskey)
     838             :     goto bad_seckey;
     839             : 
     840             :   /* Check that the pubkey algo matches the one from the public key.  */
     841           2 :   switch (canon_pk_algo (pk_algo))
     842             :     {
     843             :     case GCRY_PK_RSA:
     844           0 :       if (!is_RSA (pk->pubkey_algo))
     845           0 :         pk_algo = 0;  /* Does not match.  */
     846           0 :       break;
     847             :     case GCRY_PK_DSA:
     848           1 :       if (!is_DSA (pk->pubkey_algo))
     849           0 :         pk_algo = 0;  /* Does not match.  */
     850           1 :       break;
     851             :     case GCRY_PK_ELG:
     852           1 :       if (!is_ELGAMAL (pk->pubkey_algo))
     853           0 :         pk_algo = 0;  /* Does not match.  */
     854           1 :       break;
     855             :     case GCRY_PK_ECC:
     856           0 :       if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA)
     857             :         ;
     858           0 :       else if (pk->pubkey_algo == PUBKEY_ALGO_ECDH)
     859           0 :         is_ecdh = 1;
     860           0 :       else if (pk->pubkey_algo == PUBKEY_ALGO_EDDSA)
     861             :         ;
     862             :       else
     863           0 :         pk_algo = 0;  /* Does not match.  */
     864             :       /* For ECC we do not have the domain parameters thus fix our info.  */
     865           0 :       npkey = 1;
     866           0 :       nskey = 2;
     867           0 :       break;
     868             :     default:
     869           0 :       pk_algo = 0;   /* Oops.  */
     870           0 :       break;
     871             :     }
     872           2 :   if (!pk_algo)
     873             :     {
     874           0 :       err = gpg_error (GPG_ERR_PUBKEY_ALGO);
     875           0 :       goto leave;
     876             :     }
     877             : 
     878             :   /* This check has to go after the ecc adjustments. */
     879           2 :   if (nskey > PUBKEY_MAX_NSKEY)
     880           0 :     goto bad_seckey;
     881             : 
     882             :   /* Parse the key parameters.  */
     883           2 :   gcry_sexp_release (list);
     884           2 :   list = gcry_sexp_find_token (top_list, "skey", 0);
     885           2 :   if (!list)
     886           0 :     goto bad_seckey;
     887           2 :   for (idx=0;;)
     888             :     {
     889             :       int is_enc;
     890             : 
     891          11 :       value = gcry_sexp_nth_data (list, ++idx, &valuelen);
     892          11 :       if (!value && skeyidx >= npkey)
     893           2 :         break;  /* Ready.  */
     894             : 
     895             :       /* Check for too many parameters.  Note that depending on the
     896             :          protection mode and version number we may see less than NSKEY
     897             :          (but at least NPKEY+1) parameters.  */
     898           9 :       if (idx >= 2*nskey)
     899           0 :         goto bad_seckey;
     900           9 :       if (skeyidx >= DIM (skey)-1)
     901           0 :         goto bad_seckey;
     902             : 
     903           9 :       if (!value || valuelen != 1 || !(value[0] == '_' || value[0] == 'e'))
     904             :         goto bad_seckey;
     905           9 :       is_enc = (value[0] == 'e');
     906           9 :       value = gcry_sexp_nth_data (list, ++idx, &valuelen);
     907           9 :       if (!value || !valuelen)
     908             :         goto bad_seckey;
     909           9 :       if (is_enc)
     910             :         {
     911           2 :           void *p = xtrymalloc (valuelen);
     912           2 :           if (!p)
     913           0 :             goto outofmem;
     914           2 :           memcpy (p, value, valuelen);
     915           2 :           skey[skeyidx] = gcry_mpi_set_opaque (NULL, p, valuelen*8);
     916           2 :           if (!skey[skeyidx])
     917           0 :             goto outofmem;
     918             :         }
     919             :       else
     920             :         {
     921           7 :           if (gcry_mpi_scan (skey + skeyidx, GCRYMPI_FMT_STD,
     922             :                              value, valuelen, NULL))
     923           0 :             goto bad_seckey;
     924             :         }
     925           9 :       skeyidx++;
     926           9 :     }
     927           2 :   skey[skeyidx++] = NULL;
     928             : 
     929           2 :   gcry_sexp_release (list); list = NULL;
     930             : 
     931             :   /* We have no need for the CSUM value thus we don't parse it.  */
     932             :   /* list = gcry_sexp_find_token (top_list, "csum", 0); */
     933             :   /* if (list) */
     934             :   /*   { */
     935             :   /*     string = gcry_sexp_nth_string (list, 1); */
     936             :   /*     if (!string) */
     937             :   /*       goto bad_seckey; */
     938             :   /*     desired_csum = strtoul (string, NULL, 10); */
     939             :   /*     xfree (string); */
     940             :   /*   } */
     941             :   /* else */
     942             :   /*   desired_csum = 0; */
     943             :   /* gcry_sexp_release (list); list = NULL; */
     944             : 
     945             :   /* Get the curve name if any,  */
     946           2 :   list = gcry_sexp_find_token (top_list, "curve", 0);
     947           2 :   if (list)
     948             :     {
     949           0 :       curve = gcry_sexp_nth_string (list, 1);
     950           0 :       gcry_sexp_release (list); list = NULL;
     951             :     }
     952             : 
     953           2 :   gcry_sexp_release (top_list); top_list = NULL;
     954             : 
     955             :   /* log_debug ("XXX is_v4=%d\n", is_v4); */
     956             :   /* log_debug ("XXX pubkey_algo=%d\n", pubkey_algo); */
     957             :   /* log_debug ("XXX is_protected=%d\n", is_protected); */
     958             :   /* log_debug ("XXX protect_algo=%d\n", protect_algo); */
     959             :   /* log_printhex ("XXX iv", iv, ivlen); */
     960             :   /* log_debug ("XXX ivlen=%d\n", ivlen); */
     961             :   /* log_debug ("XXX s2k_mode=%d\n", s2k_mode); */
     962             :   /* log_debug ("XXX s2k_algo=%d\n", s2k_algo); */
     963             :   /* log_printhex ("XXX s2k_salt", s2k_salt, sizeof s2k_salt); */
     964             :   /* log_debug ("XXX s2k_count=%lu\n", (unsigned long)s2k_count); */
     965             :   /* for (idx=0; skey[idx]; idx++) */
     966             :   /*   { */
     967             :   /*     int is_enc = gcry_mpi_get_flag (skey[idx], GCRYMPI_FLAG_OPAQUE); */
     968             :   /*     log_info ("XXX skey[%d]%s:", idx, is_enc? " (enc)":""); */
     969             :   /*     if (is_enc) */
     970             :   /*       { */
     971             :   /*         void *p; */
     972             :   /*         unsigned int nbits; */
     973             :   /*         p = gcry_mpi_get_opaque (skey[idx], &nbits); */
     974             :   /*         log_printhex (NULL, p, (nbits+7)/8); */
     975             :   /*       } */
     976             :   /*     else */
     977             :   /*       gcry_mpi_dump (skey[idx]); */
     978             :   /*     log_printf ("\n"); */
     979             :   /*   } */
     980             : 
     981           2 :   if (!is_v4 || is_protected != 2 )
     982             :     {
     983             :       /* We only support the v4 format and a SHA-1 checksum.  */
     984           0 :       err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
     985           0 :       goto leave;
     986             :     }
     987             : 
     988             :   /* We need to change the received parameters for ECC algorithms.
     989             :      The transfer format has the curve name and the parameters
     990             :      separate.  We put them all into the SKEY array.  */
     991           2 :   if (canon_pk_algo (pk_algo) == GCRY_PK_ECC)
     992             :     {
     993             :       const char *oidstr;
     994             : 
     995             :       /* Assert that all required parameters are available.  We also
     996             :          check that the array does not contain more parameters than
     997             :          needed (this was used by some beta versions of 2.1.  */
     998           0 :       if (!curve || !skey[0] || !skey[1] || skey[2])
     999             :         {
    1000           0 :           err = gpg_error (GPG_ERR_INTERNAL);
    1001           0 :           goto leave;
    1002             :         }
    1003             : 
    1004           0 :       oidstr = openpgp_curve_to_oid (curve, NULL);
    1005           0 :       if (!oidstr)
    1006             :         {
    1007           0 :           log_error ("no OID known for curve '%s'\n", curve);
    1008           0 :           err = gpg_error (GPG_ERR_UNKNOWN_CURVE);
    1009           0 :           goto leave;
    1010             :         }
    1011             :       /* Put the curve's OID into into the MPI array.  This requires
    1012             :          that we shift Q and D.  For ECDH also insert the KDF parms. */
    1013           0 :       if (is_ecdh)
    1014             :         {
    1015           0 :           skey[4] = NULL;
    1016           0 :           skey[3] = skey[1];
    1017           0 :           skey[2] = gcry_mpi_copy (pk->pkey[2]);
    1018             :         }
    1019             :       else
    1020             :         {
    1021           0 :           skey[3] = NULL;
    1022           0 :           skey[2] = skey[1];
    1023             :         }
    1024           0 :       skey[1] = skey[0];
    1025           0 :       skey[0] = NULL;
    1026           0 :       err = openpgp_oid_from_str (oidstr, skey + 0);
    1027           0 :       if (err)
    1028           0 :         goto leave;
    1029             :       /* Fixup the NPKEY and NSKEY to match OpenPGP reality.  */
    1030           0 :       npkey = 2 + is_ecdh;
    1031           0 :       nskey = 3 + is_ecdh;
    1032             : 
    1033             :       /* for (idx=0; skey[idx]; idx++) */
    1034             :       /*   { */
    1035             :       /*     log_info ("YYY skey[%d]:", idx); */
    1036             :       /*     if (gcry_mpi_get_flag (skey[idx], GCRYMPI_FLAG_OPAQUE)) */
    1037             :       /*       { */
    1038             :       /*         void *p; */
    1039             :       /*         unsigned int nbits; */
    1040             :       /*         p = gcry_mpi_get_opaque (skey[idx], &nbits); */
    1041             :       /*         log_printhex (NULL, p, (nbits+7)/8); */
    1042             :       /*       } */
    1043             :       /*     else */
    1044             :       /*       gcry_mpi_dump (skey[idx]); */
    1045             :       /*     log_printf ("\n"); */
    1046             :       /*   } */
    1047             :     }
    1048             : 
    1049             :   /* Do some sanity checks.  */
    1050           2 :   if (s2k_count > 255)
    1051             :     {
    1052             :       /* We expect an already encoded S2K count.  */
    1053           0 :       err = gpg_error (GPG_ERR_INV_DATA);
    1054           0 :       goto leave;
    1055             :     }
    1056           2 :   err = openpgp_cipher_test_algo (protect_algo);
    1057           2 :   if (err)
    1058           0 :     goto leave;
    1059           2 :   err = openpgp_md_test_algo (s2k_algo);
    1060           2 :   if (err)
    1061           0 :     goto leave;
    1062             : 
    1063             :   /* Check that the public key parameters match.  Note that since
    1064             :      Libgcrypt 1.5 gcry_mpi_cmp handles opaque MPI correctly.  */
    1065           9 :   for (idx=0; idx < npkey; idx++)
    1066           7 :     if (gcry_mpi_cmp (pk->pkey[idx], skey[idx]))
    1067             :       {
    1068           0 :         err = gpg_error (GPG_ERR_BAD_PUBKEY);
    1069           0 :         goto leave;
    1070             :       }
    1071             : 
    1072             :   /* Check that the first secret key parameter in SKEY is encrypted
    1073             :      and that there are no more secret key parameters.  The latter is
    1074             :      guaranteed by the v4 packet format.  */
    1075           2 :   if (!gcry_mpi_get_flag (skey[npkey], GCRYMPI_FLAG_OPAQUE))
    1076           0 :     goto bad_seckey;
    1077           2 :   if (npkey+1 < DIM (skey) && skey[npkey+1])
    1078           0 :     goto bad_seckey;
    1079             : 
    1080             :   /* Check that the secret key parameters in PK are all set to NULL. */
    1081           4 :   for (idx=npkey; idx < nskey; idx++)
    1082           2 :     if (pk->pkey[idx])
    1083           0 :       goto bad_seckey;
    1084             : 
    1085             :   /* Now build the protection info. */
    1086           2 :   pk->seckey_info = ski = xtrycalloc (1, sizeof *ski);
    1087           2 :   if (!ski)
    1088             :     {
    1089           0 :       err = gpg_error_from_syserror ();
    1090           0 :       goto leave;
    1091             :     }
    1092             : 
    1093           2 :   ski->is_protected = 1;
    1094           2 :   ski->sha1chk = 1;
    1095           2 :   ski->algo = protect_algo;
    1096           2 :   ski->s2k.mode = s2k_mode;
    1097           2 :   ski->s2k.hash_algo = s2k_algo;
    1098             :   log_assert (sizeof ski->s2k.salt == sizeof s2k_salt);
    1099           2 :   memcpy (ski->s2k.salt, s2k_salt, sizeof s2k_salt);
    1100           2 :   ski->s2k.count = s2k_count;
    1101           2 :   log_assert (ivlen <= sizeof ski->iv);
    1102           2 :   memcpy (ski->iv, iv, ivlen);
    1103           2 :   ski->ivlen = ivlen;
    1104             : 
    1105             :   /* Store the protected secret key parameter.  */
    1106           2 :   pk->pkey[npkey] = skey[npkey];
    1107           2 :   skey[npkey] = NULL;
    1108             : 
    1109             :   /* That's it.  */
    1110             : 
    1111             :  leave:
    1112           2 :   gcry_free (curve);
    1113           2 :   gcry_sexp_release (list);
    1114           2 :   gcry_sexp_release (top_list);
    1115          13 :   for (idx=0; idx < skeyidx; idx++)
    1116          11 :     gcry_mpi_release (skey[idx]);
    1117           4 :   return err;
    1118             : 
    1119             :  bad_seckey:
    1120           0 :   err = gpg_error (GPG_ERR_BAD_SECKEY);
    1121           0 :   goto leave;
    1122             : 
    1123             :  outofmem:
    1124           0 :   err = gpg_error (GPG_ERR_ENOMEM);
    1125           0 :   goto leave;
    1126             : }
    1127             : 
    1128             : 
    1129             : /* Print an "EXPORTED" status line.  PK is the primary public key.  */
    1130             : static void
    1131           7 : print_status_exported (PKT_public_key *pk)
    1132             : {
    1133             :   char *hexfpr;
    1134             : 
    1135           7 :   if (!is_status_enabled ())
    1136          14 :     return;
    1137             : 
    1138           0 :   hexfpr = hexfingerprint (pk, NULL, 0);
    1139           0 :   write_status_text (STATUS_EXPORTED, hexfpr? hexfpr : "[?]");
    1140           0 :   xfree (hexfpr);
    1141             : }
    1142             : 
    1143             : 
    1144             : /*
    1145             :  * Receive a secret key from agent specified by HEXGRIP.
    1146             :  *
    1147             :  * Since the key data from agant is encrypted, decrypt it by CIPHERHD.
    1148             :  * Then, parse the decrypted key data in transfer format, and put
    1149             :  * secret parameters into PK.
    1150             :  *
    1151             :  * If CLEARTEXT is 0, store the secret key material
    1152             :  * passphrase-protected.  Otherwise, store secret key material in the
    1153             :  * clear.
    1154             :  *
    1155             :  * CACHE_NONCE_ADDR is used to share nonce for multple key retrievals.
    1156             :  */
    1157             : gpg_error_t
    1158           5 : receive_seckey_from_agent (ctrl_t ctrl, gcry_cipher_hd_t cipherhd,
    1159             :                            int cleartext,
    1160             :                            char **cache_nonce_addr, const char *hexgrip,
    1161             :                            PKT_public_key *pk)
    1162             : {
    1163           5 :   gpg_error_t err = 0;
    1164           5 :   unsigned char *wrappedkey = NULL;
    1165             :   size_t wrappedkeylen;
    1166           5 :   unsigned char *key = NULL;
    1167             :   size_t keylen, realkeylen;
    1168             :   gcry_sexp_t s_skey;
    1169             :   char *prompt;
    1170             : 
    1171           5 :   if (opt.verbose)
    1172           0 :     log_info ("key %s: asking agent for the secret parts\n", hexgrip);
    1173             : 
    1174           5 :   prompt = gpg_format_keydesc (pk, FORMAT_KEYDESC_EXPORT,1);
    1175           5 :   err = agent_export_key (ctrl, hexgrip, prompt, !cleartext, cache_nonce_addr,
    1176             :                           &wrappedkey, &wrappedkeylen);
    1177           5 :   xfree (prompt);
    1178             : 
    1179           5 :   if (err)
    1180           0 :     goto unwraperror;
    1181           5 :   if (wrappedkeylen < 24)
    1182             :     {
    1183           0 :       err = gpg_error (GPG_ERR_INV_LENGTH);
    1184           0 :       goto unwraperror;
    1185             :     }
    1186           5 :   keylen = wrappedkeylen - 8;
    1187           5 :   key = xtrymalloc_secure (keylen);
    1188           5 :   if (!key)
    1189             :     {
    1190           0 :       err = gpg_error_from_syserror ();
    1191           0 :       goto unwraperror;
    1192             :     }
    1193           5 :   err = gcry_cipher_decrypt (cipherhd, key, keylen, wrappedkey, wrappedkeylen);
    1194           5 :   if (err)
    1195           0 :     goto unwraperror;
    1196           5 :   realkeylen = gcry_sexp_canon_len (key, keylen, NULL, &err);
    1197           5 :   if (!realkeylen)
    1198           0 :     goto unwraperror; /* Invalid csexp.  */
    1199             : 
    1200           5 :   err = gcry_sexp_sscan (&s_skey, NULL, key, realkeylen);
    1201           5 :   if (!err)
    1202             :     {
    1203           5 :       if (cleartext)
    1204           3 :         err = cleartext_secret_key_to_openpgp (s_skey, pk);
    1205             :       else
    1206           2 :         err = transfer_format_to_openpgp (s_skey, pk);
    1207           5 :       gcry_sexp_release (s_skey);
    1208             :     }
    1209             : 
    1210             :  unwraperror:
    1211           5 :   xfree (key);
    1212           5 :   xfree (wrappedkey);
    1213           5 :   if (err)
    1214             :     {
    1215           0 :       log_error ("key %s: error receiving key from agent:"
    1216             :                  " %s%s\n", hexgrip, gpg_strerror (err),
    1217           0 :                  gpg_err_code (err) == GPG_ERR_FULLY_CANCELED?
    1218             :                  "":_(" - skipped"));
    1219             :     }
    1220           5 :   return err;
    1221             : }
    1222             : 
    1223             : 
    1224             : /* Write KEYBLOCK either to stdout or to the file set with the
    1225             :  * --output option.  This is a simplified version of do_export_stream
    1226             :  * which supports only a few export options.  */
    1227             : gpg_error_t
    1228           0 : write_keyblock_to_output (kbnode_t keyblock, int with_armor,
    1229             :                           unsigned int options)
    1230             : {
    1231             :   gpg_error_t err;
    1232             :   const char *fname;
    1233             :   iobuf_t out;
    1234             :   kbnode_t node;
    1235           0 :   armor_filter_context_t *afx = NULL;
    1236           0 :   iobuf_t out_help = NULL;
    1237           0 :   PKT_public_key *pk = NULL;
    1238             : 
    1239           0 :   fname = opt.outfile? opt.outfile : "-";
    1240           0 :   if (is_secured_filename (fname) )
    1241           0 :     return gpg_error (GPG_ERR_EPERM);
    1242             : 
    1243           0 :   out = iobuf_create (fname, 0);
    1244           0 :   if (!out)
    1245             :     {
    1246           0 :       err = gpg_error_from_syserror ();
    1247           0 :       log_error(_("can't create '%s': %s\n"), fname, gpg_strerror (err));
    1248           0 :       return err;
    1249             :     }
    1250           0 :   if (opt.verbose)
    1251           0 :     log_info (_("writing to '%s'\n"), iobuf_get_fname_nonnull (out));
    1252             : 
    1253           0 :   if ((options & (EXPORT_PKA_FORMAT|EXPORT_DANE_FORMAT)))
    1254             :     {
    1255           0 :       with_armor = 0;
    1256           0 :       out_help = iobuf_temp ();
    1257             :     }
    1258             : 
    1259           0 :   if (with_armor)
    1260             :     {
    1261           0 :       afx = new_armor_context ();
    1262           0 :       afx->what = 1;
    1263           0 :       push_armor_filter (afx, out);
    1264             :     }
    1265             : 
    1266           0 :   for (node = keyblock; node; node = node->next)
    1267             :     {
    1268           0 :       if (is_deleted_kbnode (node) || node->pkt->pkttype == PKT_RING_TRUST)
    1269           0 :         continue;
    1270           0 :       if (!pk && (node->pkt->pkttype == PKT_PUBLIC_KEY
    1271           0 :                   || node->pkt->pkttype == PKT_SECRET_KEY))
    1272           0 :         pk = node->pkt->pkt.public_key;
    1273             : 
    1274           0 :       err = build_packet (out_help? out_help : out, node->pkt);
    1275           0 :       if (err)
    1276             :         {
    1277           0 :           log_error ("build_packet(%d) failed: %s\n",
    1278           0 :                      node->pkt->pkttype, gpg_strerror (err) );
    1279           0 :           goto leave;
    1280             :         }
    1281             :     }
    1282           0 :   err = 0;
    1283             : 
    1284           0 :   if (out_help && pk)
    1285             :     {
    1286             :       const void *data;
    1287             :       size_t datalen;
    1288             : 
    1289           0 :       iobuf_flush_temp (out_help);
    1290           0 :       data = iobuf_get_temp_buffer (out_help);
    1291           0 :       datalen = iobuf_get_temp_length (out_help);
    1292             : 
    1293           0 :       err = print_pka_or_dane_records (out,
    1294             :                                        keyblock, pk, data, datalen,
    1295             :                                        (options & EXPORT_PKA_FORMAT),
    1296             :                                        (options & EXPORT_DANE_FORMAT));
    1297             :     }
    1298             : 
    1299             :  leave:
    1300           0 :   if (err)
    1301           0 :     iobuf_cancel (out);
    1302             :   else
    1303           0 :     iobuf_close (out);
    1304           0 :   iobuf_cancel (out_help);
    1305           0 :   release_armor_context (afx);
    1306           0 :   return err;
    1307             : }
    1308             : 
    1309             : 
    1310             : /*
    1311             :  * Apply the keep-uid filter to the keyblock.  The deleted nodes are
    1312             :  * marked and thus the caller should call commit_kbnode afterwards.
    1313             :  * KEYBLOCK must not have any blocks marked as deleted.
    1314             :  */
    1315             : static void
    1316           0 : apply_keep_uid_filter (kbnode_t keyblock, recsel_expr_t selector)
    1317             : {
    1318             :   kbnode_t node;
    1319             : 
    1320           0 :   for (node = keyblock->next; node; node = node->next )
    1321             :     {
    1322           0 :       if (node->pkt->pkttype == PKT_USER_ID)
    1323             :         {
    1324           0 :           if (!recsel_select (selector, impex_filter_getval, node))
    1325             :             {
    1326             :               /* log_debug ("keep-uid: deleting '%s'\n", */
    1327             :               /*            node->pkt->pkt.user_id->name); */
    1328             :               /* The UID packet and all following packets up to the
    1329             :                * next UID or a subkey.  */
    1330           0 :               delete_kbnode (node);
    1331           0 :               for (; node->next
    1332           0 :                      && node->next->pkt->pkttype != PKT_USER_ID
    1333           0 :                      && node->next->pkt->pkttype != PKT_PUBLIC_SUBKEY
    1334           0 :                      && node->next->pkt->pkttype != PKT_SECRET_SUBKEY ;
    1335           0 :                    node = node->next)
    1336           0 :                 delete_kbnode (node->next);
    1337             :             }
    1338             :           /* else */
    1339             :           /*   log_debug ("keep-uid: keeping '%s'\n", */
    1340             :           /*              node->pkt->pkt.user_id->name); */
    1341             :         }
    1342             :     }
    1343           0 : }
    1344             : 
    1345             : 
    1346             : /*
    1347             :  * Apply the drop-subkey filter to the keyblock.  The deleted nodes are
    1348             :  * marked and thus the caller should call commit_kbnode afterwards.
    1349             :  * KEYBLOCK must not have any blocks marked as deleted.
    1350             :  */
    1351             : static void
    1352           0 : apply_drop_subkey_filter (kbnode_t keyblock, recsel_expr_t selector)
    1353             : {
    1354             :   kbnode_t node;
    1355             : 
    1356           0 :   for (node = keyblock->next; node; node = node->next )
    1357             :     {
    1358           0 :       if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
    1359           0 :           || node->pkt->pkttype == PKT_SECRET_SUBKEY)
    1360             :         {
    1361           0 :           if (recsel_select (selector, impex_filter_getval, node))
    1362             :             {
    1363           0 :               log_debug ("drop-subkey: deleting a key\n");
    1364             :               /* The subkey packet and all following packets up to the
    1365             :                * next subkey.  */
    1366           0 :               delete_kbnode (node);
    1367           0 :               for (; node->next
    1368           0 :                      && node->next->pkt->pkttype != PKT_PUBLIC_SUBKEY
    1369           0 :                      && node->next->pkt->pkttype != PKT_SECRET_SUBKEY ;
    1370           0 :                    node = node->next)
    1371           0 :                 delete_kbnode (node->next);
    1372             :             }
    1373             :         }
    1374             :     }
    1375           0 : }
    1376             : 
    1377             : 
    1378             : /* Print DANE or PKA records for all user IDs in KEYBLOCK to OUT.  The
    1379             :  * data for the record is taken from (DATA,DATELEN).  PK is the public
    1380             :  * key packet with the primary key. */
    1381             : static gpg_error_t
    1382           0 : print_pka_or_dane_records (iobuf_t out, kbnode_t keyblock, PKT_public_key *pk,
    1383             :                            const void *data, size_t datalen,
    1384             :                            int print_pka, int print_dane)
    1385             : {
    1386           0 :   gpg_error_t err = 0;
    1387             :   kbnode_t kbctx, node;
    1388             :   PKT_user_id *uid;
    1389           0 :   char *mbox = NULL;
    1390             :   char hashbuf[32];
    1391           0 :   char *hash = NULL;
    1392             :   char *domain;
    1393             :   const char *s;
    1394             :   unsigned int len;
    1395           0 :   estream_t fp = NULL;
    1396           0 :   char *hexdata = NULL;
    1397             :   char *hexfpr;
    1398             : 
    1399           0 :   hexfpr = hexfingerprint (pk, NULL, 0);
    1400           0 :   hexdata = bin2hex (data, datalen, NULL);
    1401           0 :   if (!hexdata)
    1402             :     {
    1403           0 :       err = gpg_error_from_syserror ();
    1404           0 :       goto leave;
    1405             :     }
    1406           0 :   ascii_strlwr (hexdata);
    1407           0 :   fp = es_fopenmem (0, "rw,samethread");
    1408           0 :   if (!fp)
    1409             :     {
    1410           0 :       err = gpg_error_from_syserror ();
    1411           0 :       goto leave;
    1412             :     }
    1413             : 
    1414           0 :   for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0));)
    1415             :     {
    1416           0 :       if (node->pkt->pkttype != PKT_USER_ID)
    1417           0 :         continue;
    1418           0 :       uid = node->pkt->pkt.user_id;
    1419             : 
    1420           0 :       if (uid->is_expired || uid->is_revoked)
    1421           0 :         continue;
    1422             : 
    1423           0 :       xfree (mbox);
    1424           0 :       mbox = mailbox_from_userid (uid->name);
    1425           0 :       if (!mbox)
    1426           0 :         continue;
    1427             : 
    1428           0 :       domain = strchr (mbox, '@');
    1429           0 :       *domain++ = 0;
    1430             : 
    1431           0 :       if (print_pka)
    1432             :         {
    1433           0 :           es_fprintf (fp, "$ORIGIN _pka.%s.\n; %s\n; ", domain, hexfpr);
    1434           0 :           print_utf8_buffer (fp, uid->name, uid->len);
    1435           0 :           es_putc ('\n', fp);
    1436           0 :           gcry_md_hash_buffer (GCRY_MD_SHA1, hashbuf, mbox, strlen (mbox));
    1437           0 :           xfree (hash);
    1438           0 :           hash = zb32_encode (hashbuf, 8*20);
    1439           0 :           if (!hash)
    1440             :             {
    1441           0 :               err = gpg_error_from_syserror ();
    1442           0 :               goto leave;
    1443             :             }
    1444           0 :           len = strlen (hexfpr)/2;
    1445           0 :           es_fprintf (fp, "%s TYPE37 \\# %u 0006 0000 00 %02X %s\n\n",
    1446             :                       hash, 6 + len, len, hexfpr);
    1447             :         }
    1448             : 
    1449           0 :       if (print_dane && hexdata)
    1450             :         {
    1451           0 :           es_fprintf (fp, "$ORIGIN _openpgpkey.%s.\n; %s\n; ", domain, hexfpr);
    1452           0 :           print_utf8_buffer (fp, uid->name, uid->len);
    1453           0 :           es_putc ('\n', fp);
    1454           0 :           gcry_md_hash_buffer (GCRY_MD_SHA256, hashbuf, mbox, strlen (mbox));
    1455           0 :           xfree (hash);
    1456           0 :           hash = bin2hex (hashbuf, 28, NULL);
    1457           0 :           if (!hash)
    1458             :             {
    1459           0 :               err = gpg_error_from_syserror ();
    1460           0 :               goto leave;
    1461             :             }
    1462           0 :           ascii_strlwr (hash);
    1463           0 :           len = strlen (hexdata)/2;
    1464           0 :           es_fprintf (fp, "%s TYPE61 \\# %u (\n", hash, len);
    1465           0 :           for (s = hexdata; ;)
    1466             :             {
    1467           0 :               es_fprintf (fp, "\t%.64s\n", s);
    1468           0 :               if (strlen (s) < 64)
    1469           0 :                 break;
    1470           0 :               s += 64;
    1471           0 :             }
    1472           0 :           es_fputs ("\t)\n\n", fp);
    1473             :         }
    1474             :     }
    1475             : 
    1476             :   /* Make sure it is a string and write it.  */
    1477           0 :   es_fputc (0, fp);
    1478             :   {
    1479             :     void *vp;
    1480             : 
    1481           0 :     if (es_fclose_snatch (fp, &vp, NULL))
    1482             :       {
    1483           0 :         err = gpg_error_from_syserror ();
    1484           0 :         goto leave;
    1485             :       }
    1486           0 :     fp = NULL;
    1487           0 :     iobuf_writestr (out, vp);
    1488           0 :     es_free (vp);
    1489             :   }
    1490           0 :   err = 0;
    1491             : 
    1492             :  leave:
    1493           0 :   xfree (hash);
    1494           0 :   xfree (mbox);
    1495           0 :   es_fclose (fp);
    1496           0 :   xfree (hexdata);
    1497           0 :   xfree (hexfpr);
    1498           0 :   return err;
    1499             : }
    1500             : 
    1501             : 
    1502             : /* Helper for do_export_stream which writes one keyblock to OUT.  */
    1503             : static gpg_error_t
    1504           7 : do_export_one_keyblock (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid,
    1505             :                         iobuf_t out, int secret, unsigned int options,
    1506             :                         export_stats_t stats, int *any,
    1507             :                         KEYDB_SEARCH_DESC *desc, size_t ndesc,
    1508             :                         size_t descindex, gcry_cipher_hd_t cipherhd)
    1509             : {
    1510             :   gpg_error_t err;
    1511           7 :   char *cache_nonce = NULL;
    1512           7 :   subkey_list_t subkey_list = NULL;  /* Track already processed subkeys. */
    1513           7 :   int skip_until_subkey = 0;
    1514           7 :   int cleartext = 0;
    1515           7 :   char *hexgrip = NULL;
    1516           7 :   char *serialno = NULL;
    1517             :   PKT_public_key *pk;
    1518             :   u32 subkidbuf[2], *subkid;
    1519             :   kbnode_t kbctx, node;
    1520             : 
    1521          51 :   for (kbctx=NULL; (node = walk_kbnode (keyblock, &kbctx, 0)); )
    1522             :     {
    1523          37 :       if (skip_until_subkey)
    1524             :         {
    1525           0 :           if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
    1526           0 :             skip_until_subkey = 0;
    1527             :           else
    1528           0 :             continue;
    1529             :         }
    1530             : 
    1531             :       /* We used to use comment packets, but not any longer.  In
    1532             :        * case we still have comments on a key, strip them here
    1533             :        * before we call build_packet(). */
    1534          37 :       if (node->pkt->pkttype == PKT_COMMENT)
    1535           0 :         continue;
    1536             : 
    1537             :       /* Make sure that ring_trust packets never get exported. */
    1538          37 :       if (node->pkt->pkttype == PKT_RING_TRUST)
    1539           0 :         continue;
    1540             : 
    1541             :       /* If exact is set, then we only export what was requested
    1542             :        * (plus the primary key, if the user didn't specifically
    1543             :        * request it). */
    1544          37 :       if (desc[descindex].exact && node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
    1545             :         {
    1546           0 :           if (!exact_subkey_match_p (desc+descindex, node))
    1547             :             {
    1548             :               /* Before skipping this subkey, check whether any
    1549             :                * other description wants an exact match on a
    1550             :                * subkey and include that subkey into the output
    1551             :                * too.  Need to add this subkey to a list so that
    1552             :                * it won't get processed a second time.
    1553             :                *
    1554             :                * So the first step here is to check that list and
    1555             :                * skip in any case if the key is in that list.
    1556             :                *
    1557             :                * We need this whole mess because the import
    1558             :                * function of GnuPG < 2.1 is not able to merge
    1559             :                * secret keys and thus it is useless to output them
    1560             :                * as two separate keys and have import merge them.
    1561             :                */
    1562           0 :               if (subkey_in_list_p (subkey_list, node))
    1563           0 :                 skip_until_subkey = 1; /* Already processed this one. */
    1564             :               else
    1565             :                 {
    1566             :                   size_t j;
    1567             : 
    1568           0 :                   for (j=0; j < ndesc; j++)
    1569           0 :                     if (j != descindex && desc[j].exact
    1570           0 :                         && exact_subkey_match_p (desc+j, node))
    1571           0 :                       break;
    1572           0 :                   if (!(j < ndesc))
    1573           0 :                     skip_until_subkey = 1; /* No other one matching. */
    1574             :                 }
    1575             :             }
    1576             : 
    1577           0 :           if (skip_until_subkey)
    1578           0 :             continue;
    1579             : 
    1580             :           /* Mark this one as processed. */
    1581             :           {
    1582           0 :             subkey_list_t tmp = new_subkey_list_item (node);
    1583           0 :             tmp->next = subkey_list;
    1584           0 :             subkey_list = tmp;
    1585             :           }
    1586             :         }
    1587             : 
    1588          37 :       if (node->pkt->pkttype == PKT_SIGNATURE)
    1589             :         {
    1590             :           /* Do not export packets which are marked as not
    1591             :            * exportable.  */
    1592          16 :           if (!(options & EXPORT_LOCAL_SIGS)
    1593          16 :               && !node->pkt->pkt.signature->flags.exportable)
    1594           0 :             continue; /* not exportable */
    1595             : 
    1596             :           /* Do not export packets with a "sensitive" revocation key
    1597             :            * unless the user wants us to.  Note that we do export
    1598             :            * these when issuing the actual revocation (see revoke.c). */
    1599          16 :           if (!(options & EXPORT_SENSITIVE_REVKEYS)
    1600          16 :               && node->pkt->pkt.signature->revkey)
    1601             :             {
    1602             :               int i;
    1603             : 
    1604           0 :               for (i = 0; i < node->pkt->pkt.signature->numrevkeys; i++)
    1605           0 :                 if ((node->pkt->pkt.signature->revkey[i].class & 0x40))
    1606           0 :                   break;
    1607           0 :               if (i < node->pkt->pkt.signature->numrevkeys)
    1608           0 :                 continue;
    1609             :             }
    1610             :         }
    1611             : 
    1612             :       /* Don't export attribs? */
    1613          37 :       if (!(options & EXPORT_ATTRIBUTES)
    1614          14 :           && node->pkt->pkttype == PKT_USER_ID
    1615           3 :           && node->pkt->pkt.user_id->attrib_data)
    1616             :         {
    1617             :           /* Skip until we get to something that is not an attrib or a
    1618             :            * signature on an attrib.  */
    1619           0 :           while (kbctx->next && kbctx->next->pkt->pkttype == PKT_SIGNATURE)
    1620           0 :             kbctx = kbctx->next;
    1621             : 
    1622           0 :           continue;
    1623             :         }
    1624             : 
    1625          37 :       if (secret && (node->pkt->pkttype == PKT_PUBLIC_KEY
    1626          11 :                      || node->pkt->pkttype == PKT_PUBLIC_SUBKEY))
    1627             :         {
    1628           5 :           pk = node->pkt->pkt.public_key;
    1629           5 :           if (node->pkt->pkttype == PKT_PUBLIC_KEY)
    1630           3 :             subkid = NULL;
    1631             :           else
    1632             :             {
    1633           2 :               keyid_from_pk (pk, subkidbuf);
    1634           2 :               subkid = subkidbuf;
    1635             :             }
    1636             : 
    1637           5 :           if (pk->seckey_info)
    1638             :             {
    1639           0 :               log_error ("key %s: oops: seckey_info already set"
    1640             :                          " - skipped\n", keystr_with_sub (keyid, subkid));
    1641           0 :               skip_until_subkey = 1;
    1642           0 :               continue;
    1643             :             }
    1644             : 
    1645           5 :           xfree (hexgrip);
    1646           5 :           err = hexkeygrip_from_pk (pk, &hexgrip);
    1647           5 :           if (err)
    1648             :             {
    1649           0 :               log_error ("key %s: error computing keygrip: %s"
    1650             :                          " - skipped\n", keystr_with_sub (keyid, subkid),
    1651             :                          gpg_strerror (err));
    1652           0 :               skip_until_subkey = 1;
    1653           0 :               err = 0;
    1654           0 :               continue;
    1655             :             }
    1656             : 
    1657           5 :           xfree (serialno);
    1658           5 :           serialno = NULL;
    1659           5 :           if (secret == 2 && node->pkt->pkttype == PKT_PUBLIC_KEY)
    1660             :             {
    1661             :               /* We are asked not to export the secret parts of the
    1662             :                * primary key.  Make up an error code to create the
    1663             :                * stub.  */
    1664           0 :               err = GPG_ERR_NOT_FOUND;
    1665             :             }
    1666             :           else
    1667           5 :             err = agent_get_keyinfo (ctrl, hexgrip, &serialno, &cleartext);
    1668             : 
    1669           5 :           if ((!err && serialno)
    1670           0 :               && secret == 2 && node->pkt->pkttype == PKT_PUBLIC_KEY)
    1671             :             {
    1672             :               /* It does not make sense to export a key with its
    1673             :                * primary key on card using a non-key stub.  Thus we
    1674             :                * skip those keys when used with --export-secret-subkeys. */
    1675           0 :               log_info (_("key %s: key material on-card - skipped\n"),
    1676             :                         keystr_with_sub (keyid, subkid));
    1677           0 :               skip_until_subkey = 1;
    1678             :             }
    1679           5 :           else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND
    1680           5 :                    || (!err && serialno))
    1681           0 :             {
    1682             :               /* Create a key stub.  */
    1683             :               struct seckey_info *ski;
    1684             :               const char *s;
    1685             : 
    1686           0 :               pk->seckey_info = ski = xtrycalloc (1, sizeof *ski);
    1687           0 :               if (!ski)
    1688             :                 {
    1689           0 :                   err = gpg_error_from_syserror ();
    1690           0 :                   goto leave;
    1691             :                 }
    1692             : 
    1693           0 :               ski->is_protected = 1;
    1694           0 :               if (err)
    1695           0 :                 ski->s2k.mode = 1001; /* GNU dummy (no secret key).  */
    1696             :               else
    1697             :                 {
    1698           0 :                   ski->s2k.mode = 1002; /* GNU-divert-to-card.  */
    1699           0 :                   for (s=serialno; sizeof (ski->ivlen) && *s && s[1];
    1700           0 :                        ski->ivlen++, s += 2)
    1701           0 :                     ski->iv[ski->ivlen] = xtoi_2 (s);
    1702             :                 }
    1703             : 
    1704           0 :               err = build_packet (out, node->pkt);
    1705           0 :               if (!err && node->pkt->pkttype == PKT_PUBLIC_KEY)
    1706             :                 {
    1707           0 :                   stats->exported++;
    1708           0 :                   print_status_exported (node->pkt->pkt.public_key);
    1709             :                 }
    1710             :             }
    1711           5 :           else if (!err)
    1712             :             {
    1713           5 :               err = receive_seckey_from_agent (ctrl, cipherhd,
    1714             :                                                cleartext, &cache_nonce,
    1715             :                                                hexgrip, pk);
    1716           5 :               if (err)
    1717             :                 {
    1718           0 :                   if (gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
    1719           0 :                     goto leave;
    1720           0 :                   skip_until_subkey = 1;
    1721           0 :                   err = 0;
    1722             :                 }
    1723             :               else
    1724             :                 {
    1725           5 :                   err = build_packet (out, node->pkt);
    1726           5 :                   if (node->pkt->pkttype == PKT_PUBLIC_KEY)
    1727             :                     {
    1728           3 :                       stats->exported++;
    1729           3 :                       print_status_exported (node->pkt->pkt.public_key);
    1730             :                     }
    1731             :                 }
    1732             :             }
    1733             :           else
    1734             :             {
    1735           0 :               log_error ("key %s: error getting keyinfo from agent: %s"
    1736             :                          " - skipped\n", keystr_with_sub (keyid, subkid),
    1737             :                              gpg_strerror (err));
    1738           0 :               skip_until_subkey = 1;
    1739           0 :               err = 0;
    1740             :             }
    1741             : 
    1742           5 :           xfree (pk->seckey_info);
    1743           5 :           pk->seckey_info = NULL;
    1744           5 :           {
    1745             :             int i;
    1746          18 :             for (i = pubkey_get_npkey (pk->pubkey_algo);
    1747           8 :                  i < pubkey_get_nskey (pk->pubkey_algo); i++)
    1748             :               {
    1749           8 :                 gcry_mpi_release (pk->pkey[i]);
    1750           8 :                 pk->pkey[i] = NULL;
    1751             :               }
    1752             :           }
    1753             :         }
    1754             :       else /* Not secret or common packets.  */
    1755             :         {
    1756          32 :           err = build_packet (out, node->pkt);
    1757          32 :           if (!err && node->pkt->pkttype == PKT_PUBLIC_KEY)
    1758             :             {
    1759           4 :               stats->exported++;
    1760           4 :               print_status_exported (node->pkt->pkt.public_key);
    1761             :             }
    1762             :         }
    1763             : 
    1764          37 :       if (err)
    1765             :         {
    1766           0 :           log_error ("build_packet(%d) failed: %s\n",
    1767           0 :                      node->pkt->pkttype, gpg_strerror (err));
    1768           0 :           goto leave;
    1769             :         }
    1770             : 
    1771          37 :       if (!skip_until_subkey)
    1772          37 :         *any = 1;
    1773             :     }
    1774             : 
    1775             :  leave:
    1776           7 :   release_subkey_list (subkey_list);
    1777           7 :   xfree (serialno);
    1778           7 :   xfree (hexgrip);
    1779           7 :   xfree (cache_nonce);
    1780           7 :   return err;
    1781             : }
    1782             : 
    1783             : 
    1784             : /* Export the keys identified by the list of strings in USERS to the
    1785             :    stream OUT.  If SECRET is false public keys will be exported.  With
    1786             :    secret true secret keys will be exported; in this case 1 means the
    1787             :    entire secret keyblock and 2 only the subkeys.  OPTIONS are the
    1788             :    export options to apply.  If KEYBLOCK_OUT is not NULL, AND the exit
    1789             :    code is zero, a pointer to the first keyblock found and exported
    1790             :    will be stored at this address; no other keyblocks are exported in
    1791             :    this case.  The caller must free the returned keyblock.  If any
    1792             :    key has been exported true is stored at ANY. */
    1793             : static int
    1794           7 : do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
    1795             :                   kbnode_t *keyblock_out, unsigned int options,
    1796             :                   export_stats_t stats, int *any)
    1797             : {
    1798           7 :   gpg_error_t err = 0;
    1799             :   PACKET pkt;
    1800           7 :   kbnode_t keyblock = NULL;
    1801             :   kbnode_t node;
    1802             :   size_t ndesc, descindex;
    1803           7 :   KEYDB_SEARCH_DESC *desc = NULL;
    1804             :   KEYDB_HANDLE kdbhd;
    1805             :   strlist_t sl;
    1806           7 :   gcry_cipher_hd_t cipherhd = NULL;
    1807             :   struct export_stats_s dummystats;
    1808           7 :   iobuf_t out_help = NULL;
    1809             : 
    1810           7 :   if (!stats)
    1811           0 :     stats = &dummystats;
    1812           7 :   *any = 0;
    1813           7 :   init_packet (&pkt);
    1814           7 :   kdbhd = keydb_new ();
    1815           7 :   if (!kdbhd)
    1816           0 :     return gpg_error_from_syserror ();
    1817             : 
    1818             :   /* For the PKA and DANE format open a helper iobuf and for DANE
    1819             :    * enforce some options.  */
    1820           7 :   if ((options & (EXPORT_PKA_FORMAT | EXPORT_DANE_FORMAT)))
    1821             :     {
    1822           0 :       out_help = iobuf_temp ();
    1823           0 :       if ((options & EXPORT_DANE_FORMAT))
    1824           0 :         options |= EXPORT_MINIMAL | EXPORT_CLEAN;
    1825             :     }
    1826             : 
    1827           7 :   if (!users)
    1828             :     {
    1829           0 :       ndesc = 1;
    1830           0 :       desc = xcalloc (ndesc, sizeof *desc);
    1831           0 :       desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
    1832             :     }
    1833             :   else
    1834             :     {
    1835           7 :       for (ndesc=0, sl=users; sl; sl = sl->next, ndesc++)
    1836             :         ;
    1837           7 :       desc = xmalloc ( ndesc * sizeof *desc);
    1838             : 
    1839          21 :       for (ndesc=0, sl=users; sl; sl = sl->next)
    1840             :         {
    1841          14 :           if (!(err=classify_user_id (sl->d, desc+ndesc, 1)))
    1842          14 :             ndesc++;
    1843             :           else
    1844           0 :             log_error (_("key \"%s\" not found: %s\n"),
    1845           0 :                        sl->d, gpg_strerror (err));
    1846             :         }
    1847             : 
    1848           7 :       keydb_disable_caching (kdbhd);  /* We are looping the search.  */
    1849             : 
    1850             :       /* It would be nice to see which of the given users did actually
    1851             :          match one in the keyring.  To implement this we need to have
    1852             :          a found flag for each entry in desc.  To set this flag we
    1853             :          must check all those entries after a match to mark all
    1854             :          matched one - currently we stop at the first match.  To do
    1855             :          this we need an extra flag to enable this feature.  */
    1856             :     }
    1857             : 
    1858             : #ifdef ENABLE_SELINUX_HACKS
    1859             :   if (secret)
    1860             :     {
    1861             :       log_error (_("exporting secret keys not allowed\n"));
    1862             :       err = gpg_error (GPG_ERR_NOT_SUPPORTED);
    1863             :       goto leave;
    1864             :     }
    1865             : #endif
    1866             : 
    1867             :   /* For secret key export we need to setup a decryption context.  */
    1868           7 :   if (secret)
    1869             :     {
    1870           3 :       void *kek = NULL;
    1871             :       size_t keklen;
    1872             : 
    1873           3 :       err = agent_keywrap_key (ctrl, 1, &kek, &keklen);
    1874           3 :       if (err)
    1875             :         {
    1876           0 :           log_error ("error getting the KEK: %s\n", gpg_strerror (err));
    1877           0 :           goto leave;
    1878             :         }
    1879             : 
    1880             :       /* Prepare a cipher context.  */
    1881           3 :       err = gcry_cipher_open (&cipherhd, GCRY_CIPHER_AES128,
    1882             :                               GCRY_CIPHER_MODE_AESWRAP, 0);
    1883           3 :       if (!err)
    1884           3 :         err = gcry_cipher_setkey (cipherhd, kek, keklen);
    1885           3 :       if (err)
    1886             :         {
    1887           0 :           log_error ("error setting up an encryption context: %s\n",
    1888             :                      gpg_strerror (err));
    1889           0 :           goto leave;
    1890             :         }
    1891           3 :       xfree (kek);
    1892           3 :       kek = NULL;
    1893             :     }
    1894             : 
    1895             :   for (;;)
    1896             :     {
    1897             :       u32 keyid[2];
    1898             :       PKT_public_key *pk;
    1899             : 
    1900          14 :       err = keydb_search (kdbhd, desc, ndesc, &descindex);
    1901          14 :       if (!users)
    1902           0 :         desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
    1903          14 :       if (err)
    1904          14 :         break;
    1905             : 
    1906             :       /* Read the keyblock. */
    1907           7 :       release_kbnode (keyblock);
    1908           7 :       keyblock = NULL;
    1909           7 :       err = keydb_get_keyblock (kdbhd, &keyblock);
    1910           7 :       if (err)
    1911             :         {
    1912           0 :           log_error (_("error reading keyblock: %s\n"), gpg_strerror (err));
    1913           0 :           goto leave;
    1914             :         }
    1915             : 
    1916           7 :       node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
    1917           7 :       if (!node)
    1918             :         {
    1919           0 :           log_error ("public key packet not found in keyblock - skipped\n");
    1920           0 :           continue;
    1921             :         }
    1922           7 :       stats->count++;
    1923           7 :       setup_main_keyids (keyblock);  /* gpg_format_keydesc needs it.  */
    1924           7 :       pk = node->pkt->pkt.public_key;
    1925           7 :       keyid_from_pk (pk, keyid);
    1926             : 
    1927             :       /* If a secret key export is required we need to check whether
    1928             :          we have a secret key at all and if so create the seckey_info
    1929             :          structure.  */
    1930           7 :       if (secret)
    1931             :         {
    1932           3 :           if (agent_probe_any_secret_key (ctrl, keyblock))
    1933           0 :             continue;  /* No secret key (neither primary nor subkey).  */
    1934             : 
    1935             :           /* No v3 keys with GNU mode 1001. */
    1936           3 :           if (secret == 2 && pk->version == 3)
    1937             :             {
    1938           0 :               log_info (_("key %s: PGP 2.x style key - skipped\n"),
    1939             :                         keystr (keyid));
    1940           0 :               continue;
    1941             :             }
    1942             : 
    1943             :           /* The agent does not yet allow export of v3 packets.  It is
    1944             :              actually questionable whether we should allow them at
    1945             :              all.  */
    1946           3 :           if (pk->version == 3)
    1947             :             {
    1948           0 :               log_info ("key %s: PGP 2.x style key (v3) export "
    1949             :                         "not yet supported - skipped\n", keystr (keyid));
    1950           0 :               continue;
    1951             :             }
    1952           3 :           stats->secret_count++;
    1953             :         }
    1954             : 
    1955             :       /* Always do the cleaning on the public key part if requested.
    1956             :          Note that we don't yet set this option if we are exporting
    1957             :          secret keys.  Note that both export-clean and export-minimal
    1958             :          only apply to UID sigs (0x10, 0x11, 0x12, and 0x13).  A
    1959             :          designated revocation is never stripped, even with
    1960             :          export-minimal set.  */
    1961           7 :       if ((options & EXPORT_CLEAN))
    1962           0 :         clean_key (keyblock, opt.verbose, (options&EXPORT_MINIMAL), NULL, NULL);
    1963             : 
    1964           7 :       if (export_keep_uid)
    1965             :         {
    1966           0 :           commit_kbnode (&keyblock);
    1967           0 :           apply_keep_uid_filter (keyblock, export_keep_uid);
    1968           0 :           commit_kbnode (&keyblock);
    1969             :         }
    1970             : 
    1971           7 :       if (export_drop_subkey)
    1972             :         {
    1973           0 :           commit_kbnode (&keyblock);
    1974           0 :           apply_drop_subkey_filter (keyblock, export_drop_subkey);
    1975           0 :           commit_kbnode (&keyblock);
    1976             :         }
    1977             : 
    1978             :       /* And write it. */
    1979           7 :       err = do_export_one_keyblock (ctrl, keyblock, keyid,
    1980             :                                     out_help? out_help : out,
    1981             :                                     secret, options, stats, any,
    1982             :                                     desc, ndesc, descindex, cipherhd);
    1983           7 :       if (err)
    1984           0 :         break;
    1985             : 
    1986           7 :       if (keyblock_out)
    1987             :         {
    1988           0 :           *keyblock_out = keyblock;
    1989           0 :           break;
    1990             :         }
    1991             : 
    1992           7 :       if (out_help)
    1993             :         {
    1994             :           /* We want to write PKA or DANE records.  OUT_HELP has the
    1995             :            * keyblock and we print a record for each uid to OUT. */
    1996             :           const void *data;
    1997             :           size_t datalen;
    1998             : 
    1999           0 :           iobuf_flush_temp (out_help);
    2000           0 :           data = iobuf_get_temp_buffer (out_help);
    2001           0 :           datalen = iobuf_get_temp_length (out_help);
    2002             : 
    2003           0 :           err = print_pka_or_dane_records (out,
    2004             :                                            keyblock, pk, data, datalen,
    2005             :                                            (options & EXPORT_PKA_FORMAT),
    2006             :                                            (options & EXPORT_DANE_FORMAT));
    2007           0 :           if (err)
    2008           0 :             goto leave;
    2009             : 
    2010           0 :           iobuf_close (out_help);
    2011           0 :           out_help = iobuf_temp ();
    2012             :         }
    2013             : 
    2014           7 :     }
    2015           7 :   if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
    2016           7 :     err = 0;
    2017             : 
    2018             :  leave:
    2019           7 :   iobuf_cancel (out_help);
    2020           7 :   gcry_cipher_close (cipherhd);
    2021           7 :   xfree(desc);
    2022           7 :   keydb_release (kdbhd);
    2023           7 :   if (err || !keyblock_out)
    2024           7 :     release_kbnode( keyblock );
    2025           7 :   if( !*any )
    2026           0 :     log_info(_("WARNING: nothing exported\n"));
    2027           7 :   return err;
    2028             : }
    2029             : 
    2030             : 
    2031             : 
    2032             : 
    2033             : static gpg_error_t
    2034           0 : key_to_sshblob (membuf_t *mb, const char *identifier, ...)
    2035             : {
    2036             :   va_list arg_ptr;
    2037           0 :   gpg_error_t err = 0;
    2038             :   unsigned char nbuf[4];
    2039             :   unsigned char *buf;
    2040             :   size_t buflen;
    2041             :   gcry_mpi_t a;
    2042             : 
    2043           0 :   ulongtobuf (nbuf, (ulong)strlen (identifier));
    2044           0 :   put_membuf (mb, nbuf, 4);
    2045           0 :   put_membuf_str (mb, identifier);
    2046           0 :   if (!strncmp (identifier, "ecdsa-sha2-", 11))
    2047             :     {
    2048           0 :       ulongtobuf (nbuf, (ulong)strlen (identifier+11));
    2049           0 :       put_membuf (mb, nbuf, 4);
    2050           0 :       put_membuf_str (mb, identifier+11);
    2051             :     }
    2052           0 :   va_start (arg_ptr, identifier);
    2053           0 :   while ((a = va_arg (arg_ptr, gcry_mpi_t)))
    2054             :     {
    2055           0 :       err = gcry_mpi_aprint (GCRYMPI_FMT_SSH, &buf, &buflen, a);
    2056           0 :       if (err)
    2057           0 :         break;
    2058           0 :       if (!strcmp (identifier, "ssh-ed25519")
    2059           0 :           && buflen > 5 && buf[4] == 0x40)
    2060             :         {
    2061             :           /* We need to strip our 0x40 prefix.  */
    2062           0 :           put_membuf (mb, "\x00\x00\x00\x20", 4);
    2063           0 :           put_membuf (mb, buf+5, buflen-5);
    2064             :         }
    2065             :       else
    2066           0 :         put_membuf (mb, buf, buflen);
    2067           0 :       gcry_free (buf);
    2068             :     }
    2069           0 :   va_end (arg_ptr);
    2070           0 :   return err;
    2071             : }
    2072             : 
    2073             : /* Export the key identified by USERID in the SSH public key format.
    2074             :    The function exports the latest subkey with Authentication
    2075             :    capability unless the '!' suffix is used to export a specific
    2076             :    key.  */
    2077             : gpg_error_t
    2078           0 : export_ssh_key (ctrl_t ctrl, const char *userid)
    2079             : {
    2080             :   gpg_error_t err;
    2081           0 :   kbnode_t keyblock = NULL;
    2082             :   KEYDB_SEARCH_DESC desc;
    2083             :   u32 latest_date;
    2084           0 :   u32 curtime = make_timestamp ();
    2085             :   kbnode_t latest_key, node;
    2086             :   PKT_public_key *pk;
    2087             :   const char *identifier;
    2088             :   membuf_t mb;
    2089           0 :   estream_t fp = NULL;
    2090             :   struct b64state b64_state;
    2091           0 :   const char *fname = "-";
    2092             : 
    2093           0 :   init_membuf (&mb, 4096);
    2094             : 
    2095             :   /* We need to know whether the key has been specified using the
    2096             :      exact syntax ('!' suffix).  Thus we need to run a
    2097             :      classify_user_id on our own.  */
    2098           0 :   err = classify_user_id (userid, &desc, 1);
    2099             : 
    2100             :   /* Get the public key.  */
    2101           0 :   if (!err)
    2102             :     {
    2103             :       getkey_ctx_t getkeyctx;
    2104             : 
    2105           0 :       err = get_pubkey_byname (ctrl, &getkeyctx, NULL, userid, &keyblock,
    2106             :                                NULL,
    2107             :                                0  /* Only usable keys or given exact. */,
    2108             :                                1  /* No AKL lookup.  */);
    2109           0 :       if (!err)
    2110             :         {
    2111           0 :           err = getkey_next (getkeyctx, NULL, NULL);
    2112           0 :           if (!err)
    2113           0 :             err = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
    2114           0 :           else if (gpg_err_code (err) == GPG_ERR_NO_PUBKEY)
    2115           0 :             err = 0;
    2116             :         }
    2117           0 :       getkey_end (getkeyctx);
    2118             :     }
    2119           0 :   if (err)
    2120             :     {
    2121           0 :       log_error (_("key \"%s\" not found: %s\n"), userid, gpg_strerror (err));
    2122           0 :       return err;
    2123             :     }
    2124             : 
    2125             :   /* The finish_lookup code in getkey.c does not handle auth keys,
    2126             :      thus we have to duplicate the code here to find the latest
    2127             :      subkey.  However, if the key has been found using an exact match
    2128             :      ('!' notation) we use that key without any further checks and
    2129             :      even allow the use of the primary key. */
    2130           0 :   latest_date = 0;
    2131           0 :   latest_key = NULL;
    2132           0 :   for (node = keyblock; node; node = node->next)
    2133             :     {
    2134           0 :       if ((node->pkt->pkttype == PKT_PUBLIC_SUBKEY
    2135           0 :            || node->pkt->pkttype == PKT_PUBLIC_KEY)
    2136           0 :           && node->pkt->pkt.public_key->flags.exact)
    2137             :         {
    2138           0 :           latest_key = node;
    2139           0 :           break;
    2140             :         }
    2141             :     }
    2142           0 :   if (!latest_key)
    2143             :     {
    2144           0 :       for (node = keyblock; node; node = node->next)
    2145             :         {
    2146           0 :           if (node->pkt->pkttype != PKT_PUBLIC_SUBKEY)
    2147           0 :             continue;
    2148             : 
    2149           0 :           pk = node->pkt->pkt.public_key;
    2150           0 :           if (DBG_LOOKUP)
    2151           0 :             log_debug ("\tchecking subkey %08lX\n",
    2152           0 :                        (ulong) keyid_from_pk (pk, NULL));
    2153           0 :           if (!(pk->pubkey_usage & PUBKEY_USAGE_AUTH))
    2154             :             {
    2155           0 :               if (DBG_LOOKUP)
    2156           0 :                 log_debug ("\tsubkey not usable for authentication\n");
    2157           0 :               continue;
    2158             :             }
    2159           0 :           if (!pk->flags.valid)
    2160             :             {
    2161           0 :               if (DBG_LOOKUP)
    2162           0 :                 log_debug ("\tsubkey not valid\n");
    2163           0 :               continue;
    2164             :             }
    2165           0 :           if (pk->flags.revoked)
    2166             :             {
    2167           0 :               if (DBG_LOOKUP)
    2168           0 :                 log_debug ("\tsubkey has been revoked\n");
    2169           0 :               continue;
    2170             :             }
    2171           0 :           if (pk->has_expired)
    2172             :             {
    2173           0 :               if (DBG_LOOKUP)
    2174           0 :                 log_debug ("\tsubkey has expired\n");
    2175           0 :               continue;
    2176             :             }
    2177           0 :           if (pk->timestamp > curtime && !opt.ignore_valid_from)
    2178             :             {
    2179           0 :               if (DBG_LOOKUP)
    2180           0 :                 log_debug ("\tsubkey not yet valid\n");
    2181           0 :               continue;
    2182             :             }
    2183           0 :           if (DBG_LOOKUP)
    2184           0 :             log_debug ("\tsubkey might be fine\n");
    2185             :           /* In case a key has a timestamp of 0 set, we make sure that it
    2186             :              is used.  A better change would be to compare ">=" but that
    2187             :              might also change the selected keys and is as such a more
    2188             :              intrusive change.  */
    2189           0 :           if (pk->timestamp > latest_date || (!pk->timestamp && !latest_date))
    2190             :             {
    2191           0 :               latest_date = pk->timestamp;
    2192           0 :               latest_key = node;
    2193             :             }
    2194             :         }
    2195             :     }
    2196             : 
    2197           0 :   if (!latest_key)
    2198             :     {
    2199           0 :       err = gpg_error (GPG_ERR_UNUSABLE_PUBKEY);
    2200           0 :       log_error (_("key \"%s\" not found: %s\n"), userid, gpg_strerror (err));
    2201           0 :       goto leave;
    2202             :     }
    2203             : 
    2204           0 :   pk = latest_key->pkt->pkt.public_key;
    2205           0 :   if (DBG_LOOKUP)
    2206           0 :     log_debug ("\tusing key %08lX\n", (ulong) keyid_from_pk (pk, NULL));
    2207             : 
    2208           0 :   switch (pk->pubkey_algo)
    2209             :     {
    2210             :     case PUBKEY_ALGO_DSA:
    2211           0 :       identifier = "ssh-dss";
    2212           0 :       err = key_to_sshblob (&mb, identifier,
    2213             :                             pk->pkey[0], pk->pkey[1], pk->pkey[2], pk->pkey[3],
    2214             :                             NULL);
    2215           0 :       break;
    2216             : 
    2217             :     case PUBKEY_ALGO_RSA:
    2218             :     case PUBKEY_ALGO_RSA_S:
    2219           0 :       identifier = "ssh-rsa";
    2220           0 :       err = key_to_sshblob (&mb, identifier, pk->pkey[1], pk->pkey[0], NULL);
    2221           0 :       break;
    2222             : 
    2223             :     case PUBKEY_ALGO_ECDSA:
    2224             :       {
    2225             :         char *curveoid;
    2226             :         const char *curve;
    2227             : 
    2228           0 :         curveoid = openpgp_oid_to_str (pk->pkey[0]);
    2229           0 :         if (!curveoid)
    2230           0 :           err = gpg_error_from_syserror ();
    2231           0 :         else if (!(curve = openpgp_oid_to_curve (curveoid, 0)))
    2232           0 :           err = gpg_error (GPG_ERR_UNKNOWN_CURVE);
    2233             :         else
    2234             :           {
    2235           0 :             if (!strcmp (curve, "nistp256"))
    2236           0 :               identifier = "ecdsa-sha2-nistp256";
    2237           0 :             else if (!strcmp (curve, "nistp384"))
    2238           0 :               identifier = "ecdsa-sha2-nistp384";
    2239           0 :             else if (!strcmp (curve, "nistp521"))
    2240           0 :               identifier = "ecdsa-sha2-nistp521";
    2241             :             else
    2242           0 :               identifier = NULL;
    2243             : 
    2244           0 :             if (!identifier)
    2245           0 :               err = gpg_error (GPG_ERR_UNKNOWN_CURVE);
    2246             :             else
    2247           0 :               err = key_to_sshblob (&mb, identifier, pk->pkey[1], NULL);
    2248             :           }
    2249           0 :         xfree (curveoid);
    2250             :       }
    2251           0 :       break;
    2252             : 
    2253             :     case PUBKEY_ALGO_EDDSA:
    2254           0 :       if (!openpgp_oid_is_ed25519 (pk->pkey[0]))
    2255           0 :         err = gpg_error (GPG_ERR_UNKNOWN_CURVE);
    2256             :       else
    2257             :         {
    2258           0 :           identifier = "ssh-ed25519";
    2259           0 :           err = key_to_sshblob (&mb, identifier, pk->pkey[1], NULL);
    2260             :         }
    2261           0 :       break;
    2262             : 
    2263             :     case PUBKEY_ALGO_ELGAMAL_E:
    2264             :     case PUBKEY_ALGO_ELGAMAL:
    2265           0 :       err = gpg_error (GPG_ERR_UNUSABLE_PUBKEY);
    2266           0 :       break;
    2267             : 
    2268             :     default:
    2269           0 :       err = GPG_ERR_PUBKEY_ALGO;
    2270           0 :       break;
    2271             :     }
    2272             : 
    2273           0 :   if (err)
    2274           0 :     goto leave;
    2275             : 
    2276           0 :   if (opt.outfile && *opt.outfile && strcmp (opt.outfile, "-"))
    2277           0 :     fp = es_fopen ((fname = opt.outfile), "w");
    2278             :   else
    2279           0 :     fp = es_stdout;
    2280           0 :   if (!fp)
    2281             :     {
    2282           0 :       err = gpg_error_from_syserror ();
    2283           0 :       log_error (_("error creating '%s': %s\n"), fname, gpg_strerror (err));
    2284           0 :       goto leave;
    2285             :     }
    2286             : 
    2287           0 :   es_fprintf (fp, "%s ", identifier);
    2288           0 :   err = b64enc_start_es (&b64_state, fp, "");
    2289           0 :   if (err)
    2290           0 :     goto leave;
    2291             :   {
    2292             :     void *blob;
    2293             :     size_t bloblen;
    2294             : 
    2295           0 :     blob = get_membuf (&mb, &bloblen);
    2296           0 :     if (!blob)
    2297           0 :       err = gpg_error_from_syserror ();
    2298             :     else
    2299           0 :       err = b64enc_write (&b64_state, blob, bloblen);
    2300           0 :     xfree (blob);
    2301           0 :     if (err)
    2302           0 :       goto leave;
    2303             :   }
    2304           0 :   err = b64enc_finish (&b64_state);
    2305           0 :   if (err)
    2306           0 :     goto leave;
    2307           0 :   es_fprintf (fp, " openpgp:0x%08lX\n", (ulong)keyid_from_pk (pk, NULL));
    2308             : 
    2309           0 :   if (es_ferror (fp))
    2310           0 :     err = gpg_error_from_syserror ();
    2311             :   else
    2312             :     {
    2313           0 :       if (es_fclose (fp))
    2314           0 :         err = gpg_error_from_syserror ();
    2315           0 :       fp = NULL;
    2316             :     }
    2317             : 
    2318           0 :   if (err)
    2319           0 :     log_error (_("error writing '%s': %s\n"), fname, gpg_strerror (err));
    2320             : 
    2321             :  leave:
    2322           0 :   es_fclose (fp);
    2323           0 :   xfree (get_membuf (&mb, NULL));
    2324           0 :   release_kbnode (keyblock);
    2325           0 :   return err;
    2326             : }

Generated by: LCOV version 1.11