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 <https://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 6 : export_new_stats (void)
181 : {
182 : export_stats_t stats;
183 :
184 6 : return xtrycalloc (1, sizeof *stats);
185 : }
186 :
187 :
188 : /* Release an export stats object. */
189 : void
190 6 : export_release_stats (export_stats_t stats)
191 : {
192 6 : xfree (stats);
193 6 : }
194 :
195 :
196 : /* Print export statistics using the status interface. */
197 : void
198 6 : export_print_stats (export_stats_t stats)
199 : {
200 6 : if (!stats)
201 6 : return;
202 :
203 6 : 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 3 : export_pubkeys (ctrl_t ctrl, strlist_t users, unsigned int options,
227 : export_stats_t stats)
228 : {
229 3 : 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 6 : do_export (ctrl_t ctrl, strlist_t users, int secret, unsigned int options,
329 : export_stats_t stats)
330 : {
331 6 : IOBUF out = NULL;
332 : int any, rc;
333 6 : armor_filter_context_t *afx = NULL;
334 : compress_filter_context_t zfx;
335 :
336 6 : memset( &zfx, 0, sizeof zfx);
337 :
338 6 : rc = open_outfile (-1, NULL, 0, !!secret, &out );
339 6 : if (rc)
340 0 : return rc;
341 :
342 6 : 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 6 : rc = do_export_stream (ctrl, out, users, secret, NULL, options, stats, &any);
350 :
351 6 : if ( rc || !any )
352 0 : iobuf_cancel (out);
353 : else
354 6 : iobuf_close (out);
355 6 : release_armor_context (afx);
356 6 : return rc;
357 : }
358 :
359 :
360 :
361 : /* Release an entire subkey list. */
362 : static void
363 6 : release_subkey_list (subkey_list_t list)
364 : {
365 12 : while (list)
366 : {
367 0 : subkey_list_t tmp = list->next;;
368 0 : xfree (list);
369 0 : list = tmp;
370 : }
371 6 : }
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 6 : print_status_exported (PKT_public_key *pk)
1132 : {
1133 : char *hexfpr;
1134 :
1135 6 : if (!is_status_enabled ())
1136 12 : 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 6 : 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 6 : char *cache_nonce = NULL;
1512 6 : subkey_list_t subkey_list = NULL; /* Track already processed subkeys. */
1513 6 : int skip_until_subkey = 0;
1514 6 : int cleartext = 0;
1515 6 : char *hexgrip = NULL;
1516 6 : char *serialno = NULL;
1517 : PKT_public_key *pk;
1518 : u32 subkidbuf[2], *subkid;
1519 : kbnode_t kbctx, node;
1520 :
1521 40 : for (kbctx=NULL; (node = walk_kbnode (keyblock, &kbctx, 0)); )
1522 : {
1523 28 : 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 28 : if (node->pkt->pkttype == PKT_COMMENT)
1535 0 : continue;
1536 :
1537 : /* Make sure that ring_trust packets never get exported. */
1538 28 : 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 28 : 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 28 : if (node->pkt->pkttype == PKT_SIGNATURE)
1589 : {
1590 : /* Do not export packets which are marked as not
1591 : * exportable. */
1592 12 : if (!(options & EXPORT_LOCAL_SIGS)
1593 12 : && !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 12 : if (!(options & EXPORT_SENSITIVE_REVKEYS)
1600 12 : && 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 28 : 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 28 : 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 23 : err = build_packet (out, node->pkt);
1757 23 : if (!err && node->pkt->pkttype == PKT_PUBLIC_KEY)
1758 : {
1759 3 : stats->exported++;
1760 3 : print_status_exported (node->pkt->pkt.public_key);
1761 : }
1762 : }
1763 :
1764 28 : 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 28 : if (!skip_until_subkey)
1772 28 : *any = 1;
1773 : }
1774 :
1775 : leave:
1776 6 : release_subkey_list (subkey_list);
1777 6 : xfree (serialno);
1778 6 : xfree (hexgrip);
1779 6 : xfree (cache_nonce);
1780 6 : 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 6 : 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 6 : gpg_error_t err = 0;
1799 : PACKET pkt;
1800 6 : kbnode_t keyblock = NULL;
1801 : kbnode_t node;
1802 : size_t ndesc, descindex;
1803 6 : KEYDB_SEARCH_DESC *desc = NULL;
1804 : KEYDB_HANDLE kdbhd;
1805 : strlist_t sl;
1806 6 : gcry_cipher_hd_t cipherhd = NULL;
1807 : struct export_stats_s dummystats;
1808 6 : iobuf_t out_help = NULL;
1809 :
1810 6 : if (!stats)
1811 0 : stats = &dummystats;
1812 6 : *any = 0;
1813 6 : init_packet (&pkt);
1814 6 : kdbhd = keydb_new ();
1815 6 : 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 6 : 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 6 : 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 6 : for (ndesc=0, sl=users; sl; sl = sl->next, ndesc++)
1836 : ;
1837 6 : desc = xmalloc ( ndesc * sizeof *desc);
1838 :
1839 18 : for (ndesc=0, sl=users; sl; sl = sl->next)
1840 : {
1841 12 : if (!(err=classify_user_id (sl->d, desc+ndesc, 1)))
1842 12 : ndesc++;
1843 : else
1844 0 : log_error (_("key \"%s\" not found: %s\n"),
1845 0 : sl->d, gpg_strerror (err));
1846 : }
1847 :
1848 6 : 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 6 : 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 12 : err = keydb_search (kdbhd, desc, ndesc, &descindex);
1901 12 : if (!users)
1902 0 : desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
1903 12 : if (err)
1904 12 : break;
1905 :
1906 : /* Read the keyblock. */
1907 6 : release_kbnode (keyblock);
1908 6 : keyblock = NULL;
1909 6 : err = keydb_get_keyblock (kdbhd, &keyblock);
1910 6 : if (err)
1911 : {
1912 0 : log_error (_("error reading keyblock: %s\n"), gpg_strerror (err));
1913 0 : goto leave;
1914 : }
1915 :
1916 6 : node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
1917 6 : if (!node)
1918 : {
1919 0 : log_error ("public key packet not found in keyblock - skipped\n");
1920 0 : continue;
1921 : }
1922 6 : stats->count++;
1923 6 : setup_main_keyids (keyblock); /* gpg_format_keydesc needs it. */
1924 6 : pk = node->pkt->pkt.public_key;
1925 6 : 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 6 : 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 6 : if ((options & EXPORT_CLEAN))
1962 0 : clean_key (keyblock, opt.verbose, (options&EXPORT_MINIMAL), NULL, NULL);
1963 :
1964 6 : 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 6 : 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 6 : 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 6 : if (err)
1984 0 : break;
1985 :
1986 6 : if (keyblock_out)
1987 : {
1988 0 : *keyblock_out = keyblock;
1989 0 : break;
1990 : }
1991 :
1992 6 : 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 6 : }
2015 6 : if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
2016 6 : err = 0;
2017 :
2018 : leave:
2019 6 : iobuf_cancel (out_help);
2020 6 : gcry_cipher_close (cipherhd);
2021 6 : xfree(desc);
2022 6 : keydb_release (kdbhd);
2023 6 : if (err || !keyblock_out)
2024 6 : release_kbnode( keyblock );
2025 6 : if( !*any )
2026 0 : log_info(_("WARNING: nothing exported\n"));
2027 6 : return err;
2028 : }
2029 :
2030 :
2031 :
2032 :
2033 : static gpg_error_t
2034 1 : key_to_sshblob (membuf_t *mb, const char *identifier, ...)
2035 : {
2036 : va_list arg_ptr;
2037 1 : 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 1 : ulongtobuf (nbuf, (ulong)strlen (identifier));
2044 1 : put_membuf (mb, nbuf, 4);
2045 1 : put_membuf_str (mb, identifier);
2046 1 : 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 1 : va_start (arg_ptr, identifier);
2053 4 : while ((a = va_arg (arg_ptr, gcry_mpi_t)))
2054 : {
2055 2 : err = gcry_mpi_aprint (GCRYMPI_FMT_SSH, &buf, &buflen, a);
2056 2 : if (err)
2057 0 : break;
2058 2 : 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 2 : put_membuf (mb, buf, buflen);
2067 2 : gcry_free (buf);
2068 : }
2069 1 : va_end (arg_ptr);
2070 1 : 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 1 : export_ssh_key (ctrl_t ctrl, const char *userid)
2079 : {
2080 : gpg_error_t err;
2081 1 : kbnode_t keyblock = NULL;
2082 : KEYDB_SEARCH_DESC desc;
2083 : u32 latest_date;
2084 1 : u32 curtime = make_timestamp ();
2085 : kbnode_t latest_key, node;
2086 : PKT_public_key *pk;
2087 : const char *identifier;
2088 : membuf_t mb;
2089 1 : estream_t fp = NULL;
2090 : struct b64state b64_state;
2091 1 : const char *fname = "-";
2092 :
2093 1 : 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 1 : err = classify_user_id (userid, &desc, 1);
2099 :
2100 : /* Get the public key. */
2101 1 : if (!err)
2102 : {
2103 : getkey_ctx_t getkeyctx;
2104 :
2105 1 : 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 1 : if (!err)
2110 : {
2111 1 : err = getkey_next (getkeyctx, NULL, NULL);
2112 1 : if (!err)
2113 0 : err = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
2114 1 : else if (gpg_err_code (err) == GPG_ERR_NO_PUBKEY)
2115 1 : err = 0;
2116 : }
2117 1 : getkey_end (getkeyctx);
2118 : }
2119 1 : 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 1 : latest_date = 0;
2131 1 : latest_key = NULL;
2132 6 : for (node = keyblock; node; node = node->next)
2133 : {
2134 5 : if ((node->pkt->pkttype == PKT_PUBLIC_SUBKEY
2135 4 : || node->pkt->pkttype == PKT_PUBLIC_KEY)
2136 2 : && node->pkt->pkt.public_key->flags.exact)
2137 : {
2138 0 : latest_key = node;
2139 0 : break;
2140 : }
2141 : }
2142 1 : if (!latest_key)
2143 : {
2144 6 : for (node = keyblock; node; node = node->next)
2145 : {
2146 5 : if (node->pkt->pkttype != PKT_PUBLIC_SUBKEY)
2147 4 : continue;
2148 :
2149 1 : pk = node->pkt->pkt.public_key;
2150 1 : if (DBG_LOOKUP)
2151 0 : log_debug ("\tchecking subkey %08lX\n",
2152 0 : (ulong) keyid_from_pk (pk, NULL));
2153 1 : 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 1 : if (!pk->flags.valid)
2160 : {
2161 0 : if (DBG_LOOKUP)
2162 0 : log_debug ("\tsubkey not valid\n");
2163 0 : continue;
2164 : }
2165 1 : if (pk->flags.revoked)
2166 : {
2167 0 : if (DBG_LOOKUP)
2168 0 : log_debug ("\tsubkey has been revoked\n");
2169 0 : continue;
2170 : }
2171 1 : if (pk->has_expired)
2172 : {
2173 0 : if (DBG_LOOKUP)
2174 0 : log_debug ("\tsubkey has expired\n");
2175 0 : continue;
2176 : }
2177 1 : 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 1 : 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 1 : if (pk->timestamp > latest_date || (!pk->timestamp && !latest_date))
2190 : {
2191 1 : latest_date = pk->timestamp;
2192 1 : latest_key = node;
2193 : }
2194 : }
2195 : }
2196 :
2197 1 : 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 1 : pk = latest_key->pkt->pkt.public_key;
2205 1 : if (DBG_LOOKUP)
2206 0 : log_debug ("\tusing key %08lX\n", (ulong) keyid_from_pk (pk, NULL));
2207 :
2208 1 : 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 1 : identifier = "ssh-rsa";
2220 1 : err = key_to_sshblob (&mb, identifier, pk->pkey[1], pk->pkey[0], NULL);
2221 1 : 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 1 : if (err)
2274 0 : goto leave;
2275 :
2276 1 : if (opt.outfile && *opt.outfile && strcmp (opt.outfile, "-"))
2277 0 : fp = es_fopen ((fname = opt.outfile), "w");
2278 : else
2279 1 : fp = es_stdout;
2280 1 : 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 1 : es_fprintf (fp, "%s ", identifier);
2288 1 : err = b64enc_start_es (&b64_state, fp, "");
2289 1 : if (err)
2290 0 : goto leave;
2291 : {
2292 : void *blob;
2293 : size_t bloblen;
2294 :
2295 1 : blob = get_membuf (&mb, &bloblen);
2296 1 : if (!blob)
2297 0 : err = gpg_error_from_syserror ();
2298 : else
2299 1 : err = b64enc_write (&b64_state, blob, bloblen);
2300 1 : xfree (blob);
2301 1 : if (err)
2302 0 : goto leave;
2303 : }
2304 1 : err = b64enc_finish (&b64_state);
2305 1 : if (err)
2306 0 : goto leave;
2307 1 : es_fprintf (fp, " openpgp:0x%08lX\n", (ulong)keyid_from_pk (pk, NULL));
2308 :
2309 1 : if (es_ferror (fp))
2310 0 : err = gpg_error_from_syserror ();
2311 : else
2312 : {
2313 1 : if (es_fclose (fp))
2314 0 : err = gpg_error_from_syserror ();
2315 1 : fp = NULL;
2316 : }
2317 :
2318 1 : if (err)
2319 0 : log_error (_("error writing '%s': %s\n"), fname, gpg_strerror (err));
2320 :
2321 : leave:
2322 1 : es_fclose (fp);
2323 1 : xfree (get_membuf (&mb, NULL));
2324 1 : release_kbnode (keyblock);
2325 1 : return err;
2326 : }
|