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 <http://www.gnu.org/licenses/>.
41 struct revocation_reason_info
{
48 revocation_reason_build_cb( PKT_signature
*sig
, void *opaque
)
50 struct revocation_reason_info
*reason
= opaque
;
59 ud
= native_to_utf8( reason
->desc
);
62 buffer
= xmalloc( buflen
);
63 *buffer
= reason
->code
;
65 memcpy(buffer
+1, ud
, strlen(ud
) );
69 build_sig_subpkt( sig
, SIGSUBPKT_REVOC_REASON
, buffer
, buflen
);
74 /* Outputs a minimal pk (as defined by 2440) from a keyblock. A
75 minimal pk consists of the public key packet and a user ID. We try
76 and pick a user ID that has a uid signature, and include it if
79 export_minimal_pk(IOBUF out
,KBNODE keyblock
,
80 PKT_signature
*revsig
,PKT_signature
*revkey
)
84 PKT_user_id
*uid
=NULL
;
85 PKT_signature
*selfsig
=NULL
;
89 node
=find_kbnode(keyblock
,PKT_PUBLIC_KEY
);
92 log_error("key incomplete\n");
93 return G10ERR_GENERAL
;
96 keyid_from_pk(node
->pkt
->pkt
.public_key
,keyid
);
99 rc
=build_packet(out
,&pkt
);
102 log_error(_("build_packet failed: %s\n"), g10_errstr(rc
) );
107 pkt
.pkttype
=PKT_SIGNATURE
;
109 /* the revocation itself, if any. 2440 likes this to come first. */
112 pkt
.pkt
.signature
=revsig
;
113 rc
=build_packet(out
,&pkt
);
116 log_error(_("build_packet failed: %s\n"), g10_errstr(rc
) );
121 /* If a revkey in a 1F sig is present, include it too */
124 pkt
.pkt
.signature
=revkey
;
125 rc
=build_packet(out
,&pkt
);
128 log_error(_("build_packet failed: %s\n"), g10_errstr(rc
) );
137 node
=find_next_kbnode(node
,PKT_USER_ID
);
140 /* We're out of user IDs - none were self-signed. */
145 log_error(_("key %s has no user IDs\n"),keystr(keyid
));
146 return G10ERR_GENERAL
;
150 if(node
->pkt
->pkt
.user_id
->attrib_data
)
153 uid
=node
->pkt
->pkt
.user_id
;
156 while((signode
=find_next_kbnode(signode
,PKT_SIGNATURE
)))
158 if(keyid
[0]==signode
->pkt
->pkt
.signature
->keyid
[0] &&
159 keyid
[1]==signode
->pkt
->pkt
.signature
->keyid
[1] &&
160 IS_UID_SIG(signode
->pkt
->pkt
.signature
))
162 selfsig
=signode
->pkt
->pkt
.signature
;
168 pkt
.pkttype
=PKT_USER_ID
;
171 rc
=build_packet(out
,&pkt
);
174 log_error(_("build_packet failed: %s\n"), g10_errstr(rc
) );
180 pkt
.pkttype
=PKT_SIGNATURE
;
181 pkt
.pkt
.signature
=selfsig
;
183 rc
=build_packet(out
,&pkt
);
186 log_error(_("build_packet failed: %s\n"), g10_errstr(rc
) );
195 * Generate a revocation certificate for UNAME via a designated revoker
198 gen_desig_revoke( const char *uname
, strlist_t locusr
)
201 armor_filter_context_t
*afx
;
202 PKT_public_key
*pk
= NULL
;
203 PKT_secret_key
*sk
= NULL
;
204 PKT_signature
*sig
= NULL
;
206 struct revocation_reason_info
*reason
= NULL
;
208 KEYDB_SEARCH_DESC desc
;
209 KBNODE keyblock
=NULL
,node
;
212 SK_LIST sk_list
=NULL
;
216 log_error(_("can't do this in batch mode\n"));
217 return G10ERR_GENERAL
;
220 afx
= new_armor_context ();
222 kdbhd
= keydb_new (0);
223 classify_user_id (uname
, &desc
);
224 rc
= desc
.mode
? keydb_search (kdbhd
, &desc
, 1) : G10ERR_INV_USER_ID
;
226 log_error (_("key \"%s\" not found: %s\n"),uname
, g10_errstr (rc
));
230 rc
= keydb_get_keyblock (kdbhd
, &keyblock
);
232 log_error (_("error reading keyblock: %s\n"), g10_errstr(rc
) );
236 /* To parse the revkeys */
237 merge_keys_and_selfsig(keyblock
);
239 /* get the key from the keyblock */
240 node
= find_kbnode( keyblock
, PKT_PUBLIC_KEY
);
244 pk
=node
->pkt
->pkt
.public_key
;
246 keyid_from_pk(pk
,keyid
);
250 rc
=build_sk_list(locusr
,&sk_list
,0,PUBKEY_USAGE_CERT
);
255 /* Are we a designated revoker for this key? */
257 if(!pk
->revkey
&& pk
->numrevkeys
)
260 for(i
=0;i
<pk
->numrevkeys
;i
++)
269 for(list
=sk_list
;list
;list
=list
->next
)
271 byte fpr
[MAX_FINGERPRINT_LEN
];
274 fingerprint_from_sk(list
->sk
,fpr
,&fprlen
);
276 /* Don't get involved with keys that don't have 160
281 if(memcmp(fpr
,pk
->revkey
[i
].fpr
,20)==0)
286 sk
=copy_secret_key(NULL
,list
->sk
);
292 sk
=xmalloc_secure_clear(sizeof(*sk
));
293 rc
=get_seckey_byfprint(sk
,pk
->revkey
[i
].fpr
,MAX_FINGERPRINT_LEN
);
296 /* We have the revocation key */
299 PKT_signature
*revkey
= NULL
;
303 print_pubkey_info (NULL
, pk
);
306 tty_printf (_("To be revoked by:\n"));
307 print_seckey_info (sk
);
309 if(pk
->revkey
[i
].class&0x40)
310 tty_printf(_("(This is a sensitive revocation key)\n"));
313 if( !cpr_get_answer_is_yes("gen_desig_revoke.okay",
314 _("Create a designated revocation certificate for this key? (y/N) ")))
317 /* get the reason for the revocation (this is always v4) */
318 reason
= ask_revocation_reason( 1, 0, 1 );
322 rc
= check_secret_key( sk
, 0 );
327 tty_printf(_("ASCII armored output forced.\n"));
329 if( (rc
= open_outfile (GNUPG_INVALID_FD
, NULL
, 0, &out
)) )
333 afx
->hdrlines
= "Comment: A designated revocation certificate"
335 push_armor_filter (afx
, out
);
338 rc
= make_keysig_packet( &sig
, pk
, NULL
, NULL
, sk
, 0x20, 0,
340 revocation_reason_build_cb
, reason
);
342 log_error(_("make_keysig_packet failed: %s\n"), g10_errstr(rc
));
346 /* Spit out a minimal pk as well, since otherwise there is
347 no way to know which key to attach this revocation to.
348 Also include the direct key signature that contains
349 this revocation key. We're allowed to include
350 sensitive revocation keys along with a revocation, as
351 this may be the only time the recipient has seen it.
352 Note that this means that if we have multiple different
353 sensitive revocation keys in a given direct key
354 signature, we're going to include them all here. This
355 is annoying, but the good outweighs the bad, since
356 without including this a sensitive revoker can't really
357 do their job. People should not include multiple
358 sensitive revocation keys in one signature: 2440 says
359 "Note that it may be appropriate to isolate this
360 subpacket within a separate signature so that it is not
361 combined with other subpackets that need to be
368 signode
=find_next_kbnode(node
,PKT_SIGNATURE
);
374 if(keyid
[0]==signode
->pkt
->pkt
.signature
->keyid
[0] &&
375 keyid
[1]==signode
->pkt
->pkt
.signature
->keyid
[1] &&
376 IS_KEY_SIG(signode
->pkt
->pkt
.signature
))
380 for(j
=0;j
<signode
->pkt
->pkt
.signature
->numrevkeys
;j
++)
382 if(pk
->revkey
[i
].class==
383 signode
->pkt
->pkt
.signature
->revkey
[j
]->class &&
384 pk
->revkey
[i
].algid
==
385 signode
->pkt
->pkt
.signature
->revkey
[j
]->algid
&&
386 memcmp(pk
->revkey
[i
].fpr
,
387 signode
->pkt
->pkt
.signature
->revkey
[j
]->fpr
,
388 MAX_FINGERPRINT_LEN
)==0)
390 revkey
=signode
->pkt
->pkt
.signature
;
400 rc
=export_minimal_pk(out
,keyblock
,sig
,revkey
);
404 /* and issue a usage notice */
405 tty_printf(_("Revocation certificate created.\n"));
411 log_error(_("no revocation keys found for \"%s\"\n"),uname
);
415 free_public_key( pk
);
417 free_secret_key( sk
);
419 free_seckey_enc( sig
);
421 release_sk_list(sk_list
);
427 release_revocation_reason_info( reason
);
428 release_armor_context (afx
);
434 * Generate a revocation certificate for UNAME
437 gen_revoke( const char *uname
)
440 armor_filter_context_t
*afx
;
442 PKT_secret_key
*sk
; /* used as pointer into a kbnode */
443 PKT_public_key
*pk
= NULL
;
444 PKT_signature
*sig
= NULL
;
447 KBNODE keyblock
= NULL
, pub_keyblock
= NULL
;
450 struct revocation_reason_info
*reason
= NULL
;
451 KEYDB_SEARCH_DESC desc
;
455 log_error(_("can't do this in batch mode\n"));
456 return G10ERR_GENERAL
;
459 afx
= new_armor_context ();
462 /* search the userid:
463 * We don't want the whole getkey stuff here but the entire keyblock
465 kdbhd
= keydb_new (1);
466 classify_user_id (uname
, &desc
);
467 rc
= desc
.mode
? keydb_search (kdbhd
, &desc
, 1) : G10ERR_INV_USER_ID
;
470 log_error (_("secret key \"%s\" not found: %s\n"),
471 uname
, g10_errstr (rc
));
475 rc
= keydb_get_keyblock (kdbhd
, &keyblock
);
477 log_error (_("error reading keyblock: %s\n"), g10_errstr(rc
) );
481 /* get the keyid from the keyblock */
482 node
= find_kbnode( keyblock
, PKT_SECRET_KEY
);
486 /* fixme: should make a function out of this stuff,
487 * it's used all over the source */
488 sk
= node
->pkt
->pkt
.secret_key
;
489 keyid_from_sk( sk
, sk_keyid
);
490 print_seckey_info (sk
);
492 /* FIXME: We should get the public key direct from the secret one */
494 pub_keyblock
=get_pubkeyblock(sk_keyid
);
497 log_error(_("no corresponding public key: %s\n"), g10_errstr(rc
) );
501 node
=find_kbnode(pub_keyblock
,PKT_PUBLIC_KEY
);
505 pk
=node
->pkt
->pkt
.public_key
;
507 if( cmp_public_secret_key( pk
, sk
) ) {
508 log_error(_("public key does not match secret key!\n") );
514 if( !cpr_get_answer_is_yes("gen_revoke.okay",
515 _("Create a revocation certificate for this key? (y/N) ")) )
521 if(sk
->version
>=4 || opt
.force_v4_certs
) {
522 /* get the reason for the revocation */
523 reason
= ask_revocation_reason( 1, 0, 1 );
524 if( !reason
) { /* user decided to cancel */
530 switch( is_secret_key_protected( sk
) ) {
532 log_error(_("unknown protection algorithm\n"));
533 rc
= G10ERR_PUBKEY_ALGO
;
536 tty_printf (_("Secret parts of primary key are not available.\n"));
537 rc
= G10ERR_NO_SECKEY
;
540 tty_printf(_("NOTE: This key is not protected!\n"));
543 rc
= check_secret_key( sk
, 0 );
551 tty_printf(_("ASCII armored output forced.\n"));
553 if( (rc
= open_outfile (GNUPG_INVALID_FD
, NULL
, 0, &out
)) )
557 afx
->hdrlines
= "Comment: A revocation certificate should follow\n";
558 push_armor_filter (afx
, out
);
561 rc
= make_keysig_packet( &sig
, pk
, NULL
, NULL
, sk
, 0x20, 0,
562 opt
.force_v4_certs
?4:0, 0, 0,
563 revocation_reason_build_cb
, reason
);
565 log_error(_("make_keysig_packet failed: %s\n"), g10_errstr(rc
));
569 if(PGP2
|| PGP6
|| PGP7
|| PGP8
)
571 /* Use a minimal pk for PGPx mode, since PGP can't import bare
572 revocation certificates. */
573 rc
=export_minimal_pk(out
,pub_keyblock
,sig
,NULL
);
580 pkt
.pkttype
= PKT_SIGNATURE
;
581 pkt
.pkt
.signature
= sig
;
583 rc
= build_packet( out
, &pkt
);
585 log_error(_("build_packet failed: %s\n"), g10_errstr(rc
) );
590 /* and issue a usage notice */
591 tty_printf(_("Revocation certificate created.\n\n"
592 "Please move it to a medium which you can hide away; if Mallory gets\n"
593 "access to this certificate he can use it to make your key unusable.\n"
594 "It is smart to print this certificate and store it away, just in case\n"
595 "your media become unreadable. But have some caution: The print system of\n"
596 "your machine might store the data and make it available to others!\n"));
600 free_seckey_enc( sig
);
601 release_kbnode( keyblock
);
602 release_kbnode( pub_keyblock
);
603 keydb_release (kdbhd
);
608 release_revocation_reason_info( reason
);
609 release_armor_context (afx
);
615 struct revocation_reason_info
*
616 ask_revocation_reason( int key_rev
, int cert_rev
, int hint
)
619 char *description
= NULL
;
620 struct revocation_reason_info
*reason
;
621 const char *text_0
= _("No reason specified");
622 const char *text_1
= _("Key has been compromised");
623 const char *text_2
= _("Key is superseded");
624 const char *text_3
= _("Key is no longer used");
625 const char *text_4
= _("User ID is no longer valid");
626 const char *code_text
= NULL
;
633 tty_printf(_("Please select the reason for the revocation:\n"));
634 tty_printf( " 0 = %s\n", text_0
);
636 tty_printf(" 1 = %s\n", text_1
);
638 tty_printf(" 2 = %s\n", text_2
);
640 tty_printf(" 3 = %s\n", text_3
);
642 tty_printf(" 4 = %s\n", text_4
);
643 tty_printf( " Q = %s\n", _("Cancel") );
645 tty_printf(_("(Probably you want to select %d here)\n"), hint
);
649 char *answer
= cpr_get("ask_revocation_reason.code",
650 _("Your decision? "));
651 trim_spaces( answer
);
653 if( *answer
== 'q' || *answer
== 'Q')
654 return NULL
; /* cancel */
655 if( hint
&& !*answer
)
657 else if(!digitp( answer
) )
663 code
= 0x00; /* no particular reason */
666 else if( key_rev
&& n
== 1 ) {
667 code
= 0x02; /* key has been compromised */
670 else if( key_rev
&& n
== 2 ) {
671 code
= 0x01; /* key is superseded */
674 else if( key_rev
&& n
== 3 ) {
675 code
= 0x03; /* key is no longer used */
678 else if( cert_rev
&& n
== 4 ) {
679 code
= 0x20; /* uid is no longer valid */
683 tty_printf(_("Invalid selection.\n"));
686 tty_printf(_("Enter an optional description; "
687 "end it with an empty line:\n") );
689 char *answer
= cpr_get("ask_revocation_reason.text", "> " );
690 trim_trailing_ws( answer
, strlen(answer
) );
698 char *p
= make_printable_string( answer
, strlen(answer
), 0 );
704 description
= xstrdup(answer
);
706 char *p
= xmalloc( strlen(description
) + strlen(answer
) + 2 );
707 strcpy(stpcpy(stpcpy( p
, description
),"\n"),answer
);
714 tty_printf(_("Reason for revocation: %s\n"), code_text
);
716 tty_printf(_("(No description given)\n") );
718 tty_printf("%s\n", description
);
720 } while( !cpr_get_answer_is_yes("ask_revocation_reason.okay",
721 _("Is this okay? (y/N) ")) );
723 reason
= xmalloc( sizeof *reason
);
725 reason
->desc
= description
;
730 release_revocation_reason_info( struct revocation_reason_info
*reason
)
733 xfree( reason
->desc
);