1 /* revoke.c - Create recovation certificates.
2 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
3 * 2004 Free Software Foundation, Inc.
5 * This file is part of GnuPG.
7 * GnuPG is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * GnuPG is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <https://www.gnu.org/licenses/>.
31 #include "../common/status.h"
33 #include "../common/util.h"
35 #include "../common/ttyio.h"
36 #include "../common/i18n.h"
37 #include "call-agent.h"
39 struct revocation_reason_info {
46 revocation_reason_build_cb( PKT_signature *sig, void *opaque )
48 struct revocation_reason_info *reason = opaque;
57 ud = native_to_utf8( reason->desc );
60 buffer = xmalloc( buflen );
61 *buffer = reason->code;
63 memcpy(buffer+1, ud, strlen(ud) );
67 build_sig_subpkt( sig, SIGSUBPKT_REVOC_REASON, buffer, buflen );
72 /* Outputs a minimal pk (as defined by 2440) from a keyblock. A
73 minimal pk consists of the public key packet and a user ID. We try
74 and pick a user ID that has a uid signature, and include it if
77 export_minimal_pk(IOBUF out,KBNODE keyblock,
78 PKT_signature *revsig,PKT_signature *revkey)
82 PKT_user_id *uid=NULL;
83 PKT_signature *selfsig=NULL;
87 node=find_kbnode(keyblock,PKT_PUBLIC_KEY);
90 log_error("key incomplete\n");
91 return GPG_ERR_GENERAL;
94 keyid_from_pk(node->pkt->pkt.public_key,keyid);
97 rc=build_packet(out,&pkt);
100 log_error(_("build_packet failed: %s\n"), gpg_strerror (rc) );
105 pkt.pkttype=PKT_SIGNATURE;
107 /* the revocation itself, if any. 2440 likes this to come first. */
110 pkt.pkt.signature=revsig;
111 rc=build_packet(out,&pkt);
114 log_error("build_packet failed: %s\n", gpg_strerror (rc) );
119 /* If a revkey in a 1F sig is present, include it too */
122 pkt.pkt.signature=revkey;
123 rc=build_packet(out,&pkt);
126 log_error(_("build_packet failed: %s\n"), gpg_strerror (rc) );
135 node=find_next_kbnode(node,PKT_USER_ID);
138 /* We're out of user IDs - none were self-signed. */
143 log_error(_("key %s has no user IDs\n"),keystr(keyid));
144 return GPG_ERR_GENERAL;
148 if(node->pkt->pkt.user_id->attrib_data)
151 uid=node->pkt->pkt.user_id;
154 while((signode=find_next_kbnode(signode,PKT_SIGNATURE)))
156 if(keyid[0]==signode->pkt->pkt.signature->keyid[0] &&
157 keyid[1]==signode->pkt->pkt.signature->keyid[1] &&
158 IS_UID_SIG(signode->pkt->pkt.signature))
160 selfsig=signode->pkt->pkt.signature;
166 pkt.pkttype=PKT_USER_ID;
169 rc=build_packet(out,&pkt);
172 log_error(_("build_packet failed: %s\n"), gpg_strerror (rc) );
178 pkt.pkttype=PKT_SIGNATURE;
179 pkt.pkt.signature=selfsig;
181 rc=build_packet(out,&pkt);
184 log_error(_("build_packet failed: %s\n"), gpg_strerror (rc) );
193 * Generate a revocation certificate for UNAME via a designated revoker
196 gen_desig_revoke (ctrl_t ctrl, const char *uname, strlist_t locusr)
199 armor_filter_context_t *afx;
200 PKT_public_key *pk = NULL;
201 PKT_public_key *pk2 = NULL;
202 PKT_signature *sig = NULL;
204 struct revocation_reason_info *reason = NULL;
206 KEYDB_SEARCH_DESC desc;
207 KBNODE keyblock=NULL,node;
210 SK_LIST sk_list=NULL;
214 log_error(_("can't do this in batch mode\n"));
215 return GPG_ERR_GENERAL;
218 afx = new_armor_context ();
220 kdbhd = keydb_new ();
223 rc = gpg_error_from_syserror ();
226 rc = classify_user_id (uname, &desc, 1);
228 rc = keydb_search (kdbhd, &desc, 1, NULL);
230 log_error (_("key \"%s\" not found: %s\n"),uname, gpg_strerror (rc));
234 rc = keydb_get_keyblock (kdbhd, &keyblock );
236 log_error (_("error reading keyblock: %s\n"), gpg_strerror (rc) );
240 /* To parse the revkeys */
241 merge_keys_and_selfsig (ctrl, keyblock);
243 /* get the key from the keyblock */
244 node = find_kbnode( keyblock, PKT_PUBLIC_KEY );
248 pk=node->pkt->pkt.public_key;
250 keyid_from_pk(pk,keyid);
254 rc = build_sk_list (ctrl, locusr, &sk_list, PUBKEY_USAGE_CERT);
259 /* Are we a designated revoker for this key? */
261 if(!pk->revkey && pk->numrevkeys)
264 for(i=0;i<pk->numrevkeys;i++)
268 free_public_key (pk2);
273 for(list=sk_list;list;list=list->next)
275 byte fpr[MAX_FINGERPRINT_LEN];
278 fingerprint_from_pk (list->pk, fpr, &fprlen);
280 /* Don't get involved with keys that don't have 160
285 if(memcmp(fpr,pk->revkey[i].fpr,20)==0)
290 pk2 = copy_public_key (NULL, list->pk);
296 pk2 = xmalloc_clear (sizeof *pk2);
297 rc = get_pubkey_byfprint (ctrl, pk2, NULL,
298 pk->revkey[i].fpr, MAX_FINGERPRINT_LEN);
301 /* We have the revocation key. */
304 PKT_signature *revkey = NULL;
308 print_pubkey_info (ctrl, NULL, pk);
311 tty_printf (_("To be revoked by:\n"));
312 print_seckey_info (ctrl, pk2);
314 if(pk->revkey[i].class&0x40)
315 tty_printf(_("(This is a sensitive revocation key)\n"));
318 rc = agent_probe_secret_key (ctrl, pk2);
321 tty_printf (_("Secret key is not available.\n"));
325 if( !cpr_get_answer_is_yes("gen_desig_revoke.okay",
326 _("Create a designated revocation certificate for this key? (y/N) ")))
329 /* get the reason for the revocation (this is always v4) */
330 reason = ask_revocation_reason( 1, 0, 1 );
335 tty_printf(_("ASCII armored output forced.\n"));
337 if( (rc = open_outfile (-1, NULL, 0, 1, &out )) )
341 afx->hdrlines = "Comment: A designated revocation certificate"
343 push_armor_filter (afx, out);
346 rc = make_keysig_packet (ctrl, &sig, pk, NULL, NULL, pk2, 0x20, 0,
348 revocation_reason_build_cb, reason,
351 log_error(_("make_keysig_packet failed: %s\n"), gpg_strerror (rc));
355 /* Spit out a minimal pk as well, since otherwise there is
356 no way to know which key to attach this revocation to.
357 Also include the direct key signature that contains
358 this revocation key. We're allowed to include
359 sensitive revocation keys along with a revocation, as
360 this may be the only time the recipient has seen it.
361 Note that this means that if we have multiple different
362 sensitive revocation keys in a given direct key
363 signature, we're going to include them all here. This
364 is annoying, but the good outweighs the bad, since
365 without including this a sensitive revoker can't really
366 do their job. People should not include multiple
367 sensitive revocation keys in one signature: 2440 says
368 "Note that it may be appropriate to isolate this
369 subpacket within a separate signature so that it is not
370 combined with other subpackets that need to be
377 signode=find_next_kbnode(node,PKT_SIGNATURE);
383 if(keyid[0]==signode->pkt->pkt.signature->keyid[0] &&
384 keyid[1]==signode->pkt->pkt.signature->keyid[1] &&
385 IS_KEY_SIG(signode->pkt->pkt.signature))
389 for(j=0;j<signode->pkt->pkt.signature->numrevkeys;j++)
391 if(pk->revkey[i].class==
392 signode->pkt->pkt.signature->revkey[j].class &&
393 pk->revkey[i].algid==
394 signode->pkt->pkt.signature->revkey[j].algid &&
395 memcmp(pk->revkey[i].fpr,
396 signode->pkt->pkt.signature->revkey[j].fpr,
397 MAX_FINGERPRINT_LEN)==0)
399 revkey=signode->pkt->pkt.signature;
409 rc=export_minimal_pk(out,keyblock,sig,revkey);
413 /* and issue a usage notice */
414 tty_printf(_("Revocation certificate created.\n"));
420 log_error(_("no revocation keys found for \"%s\"\n"),uname);
423 free_public_key (pk);
424 free_public_key (pk2);
426 free_seckey_enc( sig );
428 release_sk_list(sk_list);
434 release_revocation_reason_info( reason );
435 release_armor_context (afx);
440 /* Common core to create the revocation. FILENAME may be NULL to write
441 to stdout or the filename given by --output. REASON describes the
442 revocation reason. PSK is the public primary key - we expect that
443 a corresponding secret key is available. KEYBLOCK is the entire
444 KEYBLOCK which is used in PGP mode to write a minimal key and not
445 just the naked revocation signature; it may be NULL. If LEADINTEXT
446 is not NULL, it is written right before the (armored) output.*/
448 create_revocation (ctrl_t ctrl,
449 const char *filename,
450 struct revocation_reason_info *reason,
453 const char *leadintext, int suffix,
454 const char *cache_nonce)
458 armor_filter_context_t *afx;
459 PKT_signature *sig = NULL;
462 afx = new_armor_context ();
464 if ((rc = open_outfile (-1, filename, suffix, 1, &out)))
468 iobuf_writestr (out, leadintext);
471 afx->hdrlines = "Comment: This is a revocation certificate\n";
472 push_armor_filter (afx, out);
474 rc = make_keysig_packet (ctrl, &sig, psk, NULL, NULL, psk, 0x20, 0,
476 revocation_reason_build_cb, reason, cache_nonce);
479 log_error (_("make_keysig_packet failed: %s\n"), gpg_strerror (rc));
483 if (keyblock && (PGP6 || PGP7 || PGP8))
485 /* Use a minimal pk for PGPx mode, since PGP can't import bare
486 revocation certificates. */
487 rc = export_minimal_pk (out, keyblock, sig, NULL);
494 pkt.pkttype = PKT_SIGNATURE;
495 pkt.pkt.signature = sig;
497 rc = build_packet (out, &pkt);
500 log_error (_("build_packet failed: %s\n"), gpg_strerror (rc));
507 free_seckey_enc (sig);
512 release_armor_context (afx);
517 /* This function is used to generate a standard revocation certificate
518 by gpg's interactive key generation function. The certificate is
519 stored at a dedicated place in a slightly modified form to avoid an
520 accidental import. PSK is the primary key; a corresponding secret
521 key must be available. CACHE_NONCE is optional but can be used to
522 help gpg-agent to avoid an extra passphrase prompt. */
524 gen_standard_revoke (ctrl_t ctrl, PKT_public_key *psk, const char *cache_nonce)
528 struct revocation_reason_info reason;
529 char *dir, *tmpstr, *fname;
537 dir = get_openpgp_revocdir (gnupg_homedir ());
538 tmpstr = hexfingerprint (psk, NULL, 0);
541 rc = gpg_error_from_syserror ();
545 fname = strconcat (dir, DIRSEP_S, tmpstr, NULL);
548 rc = gpg_error_from_syserror ();
556 keyid_from_pk (psk, keyid);
558 memfp = es_fopenmem (0, "r+");
560 log_fatal ("error creating memory stream\n");
562 orig_codeset = i18n_switchto_utf8 ();
564 es_fprintf (memfp, "%s\n\n",
565 _("This is a revocation certificate for the OpenPGP key:"));
567 print_key_line (ctrl, memfp, psk, 0);
569 if (opt.keyid_format != KF_NONE)
570 print_fingerprint (ctrl, memfp, psk, 3);
572 kl = opt.keyid_format == KF_NONE? 0 : keystrlen ();
574 tmpstr = get_user_id (ctrl, keyid, &len);
575 es_fprintf (memfp, "uid%*s%.*s\n\n",
580 es_fprintf (memfp, "%s\n\n%s\n\n%s\n\n:",
581 _("A revocation certificate is a kind of \"kill switch\" to publicly\n"
582 "declare that a key shall not anymore be used. It is not possible\n"
583 "to retract such a revocation certificate once it has been published."),
584 _("Use it to revoke this key in case of a compromise or loss of\n"
585 "the secret key. However, if the secret key is still accessible,\n"
586 "it is better to generate a new revocation certificate and give\n"
587 "a reason for the revocation. For details see the description of\n"
588 "of the gpg command \"--generate-revocation\" in the "
590 _("To avoid an accidental use of this file, a colon has been inserted\n"
591 "before the 5 dashes below. Remove this colon with a text editor\n"
592 "before importing and publishing this revocation certificate."));
596 i18n_switchback (orig_codeset);
598 if (es_fclose_snatch (memfp, &leadin, NULL))
599 log_fatal ("error snatching memory stream\n");
601 reason.code = 0x00; /* No particular reason. */
603 old_outfile = opt.outfile;
605 rc = create_revocation (ctrl,
606 fname, &reason, psk, NULL, leadin, 3, cache_nonce);
607 opt.outfile = old_outfile;
608 if (!rc && !opt.quiet)
609 log_info (_("revocation certificate stored as '%s.rev'\n"), fname);
620 * Generate a revocation certificate for UNAME
623 gen_revoke (ctrl_t ctrl, const char *uname)
628 kbnode_t keyblock = NULL;
631 struct revocation_reason_info *reason = NULL;
632 KEYDB_SEARCH_DESC desc;
636 log_error(_("can't do this in batch mode\n"));
637 return GPG_ERR_GENERAL;
640 /* Search the userid; we don't want the whole getkey stuff here. */
641 kdbhd = keydb_new ();
644 rc = gpg_error_from_syserror ();
647 rc = classify_user_id (uname, &desc, 1);
649 rc = keydb_search (kdbhd, &desc, 1, NULL);
652 if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
653 log_error (_("secret key \"%s\" not found\n"), uname);
655 log_error (_("secret key \"%s\" not found: %s\n"),
656 uname, gpg_strerror (rc));
660 rc = keydb_get_keyblock (kdbhd, &keyblock );
663 log_error (_("error reading keyblock: %s\n"), gpg_strerror (rc) );
667 rc = keydb_search (kdbhd, &desc, 1, NULL);
668 if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
677 /* TRANSLATORS: The %s prints a key specification which
678 for example has been given at the command line. Several lines
679 lines with secret key infos are printed after this message. */
680 log_error (_("'%s' matches multiple secret keys:\n"), uname);
682 info = format_seckey_info (ctrl, keyblock->pkt->pkt.public_key);
683 log_error (" %s\n", info);
685 release_kbnode (keyblock);
687 rc = keydb_get_keyblock (kdbhd, &keyblock);
690 info = format_seckey_info (ctrl, keyblock->pkt->pkt.public_key);
691 log_info (" %s\n", info);
693 release_kbnode (keyblock);
696 rc = keydb_search (kdbhd, &desc, 1, NULL);
698 rc = keydb_get_keyblock (kdbhd, &keyblock);
701 rc = GPG_ERR_AMBIGUOUS_NAME;
707 log_error (_("error searching the keyring: %s\n"), gpg_strerror (rc));
711 /* Get the keyid from the keyblock. */
712 node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
716 psk = node->pkt->pkt.public_key;
717 rc = agent_probe_secret_key (NULL, psk);
720 log_error (_("secret key \"%s\" not found: %s\n"),
721 uname, gpg_strerror (rc));
725 keyid_from_pk (psk, keyid );
726 print_seckey_info (ctrl, psk);
729 if (!cpr_get_answer_is_yes ("gen_revoke.okay",
730 _("Create a revocation certificate for this key? (y/N) ")))
736 /* Get the reason for the revocation. */
737 reason = ask_revocation_reason (1, 0, 1);
740 /* User decided to cancel. */
746 tty_printf (_("ASCII armored output forced.\n"));
748 rc = create_revocation (ctrl, NULL, reason, psk, keyblock, NULL, 0, NULL);
752 /* and issue a usage notice */
754 "Revocation certificate created.\n\n"
755 "Please move it to a medium which you can hide away; if Mallory gets\n"
756 "access to this certificate he can use it to make your key unusable.\n"
757 "It is smart to print this certificate and store it away, just in case\n"
758 "your media become unreadable. But have some caution: The print system of\n"
759 "your machine might store the data and make it available to others!\n"));
762 release_kbnode (keyblock);
763 keydb_release (kdbhd);
764 release_revocation_reason_info( reason );
770 struct revocation_reason_info *
771 ask_revocation_reason( int key_rev, int cert_rev, int hint )
774 char *description = NULL;
775 struct revocation_reason_info *reason;
776 const char *text_0 = _("No reason specified");
777 const char *text_1 = _("Key has been compromised");
778 const char *text_2 = _("Key is superseded");
779 const char *text_3 = _("Key is no longer used");
780 const char *text_4 = _("User ID is no longer valid");
781 const char *code_text = NULL;
788 tty_printf(_("Please select the reason for the revocation:\n"));
789 tty_printf( " 0 = %s\n", text_0 );
791 tty_printf(" 1 = %s\n", text_1 );
793 tty_printf(" 2 = %s\n", text_2 );
795 tty_printf(" 3 = %s\n", text_3 );
797 tty_printf(" 4 = %s\n", text_4 );
798 tty_printf( " Q = %s\n", _("Cancel") );
800 tty_printf(_("(Probably you want to select %d here)\n"), hint );
804 char *answer = cpr_get("ask_revocation_reason.code",
805 _("Your decision? "));
806 trim_spaces( answer );
808 if( *answer == 'q' || *answer == 'Q')
809 return NULL; /* cancel */
810 if( hint && !*answer )
812 else if(!digitp( answer ) )
818 code = 0x00; /* no particular reason */
821 else if( key_rev && n == 1 ) {
822 code = 0x02; /* key has been compromised */
825 else if( key_rev && n == 2 ) {
826 code = 0x01; /* key is superseded */
829 else if( key_rev && n == 3 ) {
830 code = 0x03; /* key is no longer used */
833 else if( cert_rev && n == 4 ) {
834 code = 0x20; /* uid is no longer valid */
838 tty_printf(_("Invalid selection.\n"));
841 tty_printf(_("Enter an optional description; "
842 "end it with an empty line:\n") );
844 char *answer = cpr_get("ask_revocation_reason.text", "> " );
845 trim_trailing_ws( answer, strlen(answer) );
853 char *p = make_printable_string( answer, strlen(answer), 0 );
859 description = xstrdup(answer);
861 char *p = xmalloc( strlen(description) + strlen(answer) + 2 );
862 strcpy(stpcpy(stpcpy( p, description),"\n"),answer);
869 tty_printf(_("Reason for revocation: %s\n"), code_text );
871 tty_printf(_("(No description given)\n") );
873 tty_printf("%s\n", description );
875 } while( !cpr_get_answer_is_yes("ask_revocation_reason.okay",
876 _("Is this okay? (y/N) ")) );
878 reason = xmalloc( sizeof *reason );
880 reason->desc = description;
884 struct revocation_reason_info *
885 get_default_uid_revocation_reason(void)
887 struct revocation_reason_info *reason;
888 reason = xmalloc( sizeof *reason );
889 reason->code = 0x20; /* uid is no longer valid */
890 reason->desc = strdup(""); /* no text */
895 release_revocation_reason_info( struct revocation_reason_info *reason )
898 xfree( reason->desc );