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 2 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, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
43 struct revocation_reason_info
{
50 revocation_reason_build_cb( PKT_signature
*sig
, void *opaque
)
52 struct revocation_reason_info
*reason
= opaque
;
61 ud
= native_to_utf8( reason
->desc
);
64 buffer
= xmalloc( buflen
);
65 *buffer
= reason
->code
;
67 memcpy(buffer
+1, ud
, strlen(ud
) );
71 build_sig_subpkt( sig
, SIGSUBPKT_REVOC_REASON
, buffer
, buflen
);
76 /* Outputs a minimal pk (as defined by 2440) from a keyblock. A
77 minimal pk consists of the public key packet and a user ID. We try
78 and pick a user ID that has a uid signature, and include it if
81 export_minimal_pk(IOBUF out
,KBNODE keyblock
,
82 PKT_signature
*revsig
,PKT_signature
*revkey
)
86 PKT_user_id
*uid
=NULL
;
87 PKT_signature
*selfsig
=NULL
;
91 node
=find_kbnode(keyblock
,PKT_PUBLIC_KEY
);
94 log_error("key incomplete\n");
95 return G10ERR_GENERAL
;
98 keyid_from_pk(node
->pkt
->pkt
.public_key
,keyid
);
101 rc
=build_packet(out
,&pkt
);
104 log_error(_("build_packet failed: %s\n"), g10_errstr(rc
) );
109 pkt
.pkttype
=PKT_SIGNATURE
;
111 /* the revocation itself, if any. 2440 likes this to come first. */
114 pkt
.pkt
.signature
=revsig
;
115 rc
=build_packet(out
,&pkt
);
118 log_error(_("build_packet failed: %s\n"), g10_errstr(rc
) );
123 /* If a revkey in a 1F sig is present, include it too */
126 pkt
.pkt
.signature
=revkey
;
127 rc
=build_packet(out
,&pkt
);
130 log_error(_("build_packet failed: %s\n"), g10_errstr(rc
) );
139 node
=find_next_kbnode(node
,PKT_USER_ID
);
142 /* We're out of user IDs - none were self-signed. */
147 log_error(_("key %s has no user IDs\n"),keystr(keyid
));
148 return G10ERR_GENERAL
;
152 if(node
->pkt
->pkt
.user_id
->attrib_data
)
155 uid
=node
->pkt
->pkt
.user_id
;
158 while((signode
=find_next_kbnode(signode
,PKT_SIGNATURE
)))
160 if(keyid
[0]==signode
->pkt
->pkt
.signature
->keyid
[0] &&
161 keyid
[1]==signode
->pkt
->pkt
.signature
->keyid
[1] &&
162 IS_UID_SIG(signode
->pkt
->pkt
.signature
))
164 selfsig
=signode
->pkt
->pkt
.signature
;
170 pkt
.pkttype
=PKT_USER_ID
;
173 rc
=build_packet(out
,&pkt
);
176 log_error(_("build_packet failed: %s\n"), g10_errstr(rc
) );
182 pkt
.pkttype
=PKT_SIGNATURE
;
183 pkt
.pkt
.signature
=selfsig
;
185 rc
=build_packet(out
,&pkt
);
188 log_error(_("build_packet failed: %s\n"), g10_errstr(rc
) );
197 * Generate a revocation certificate for UNAME via a designated revoker
200 gen_desig_revoke( const char *uname
, strlist_t locusr
)
203 armor_filter_context_t
*afx
;
204 PKT_public_key
*pk
= NULL
;
205 PKT_secret_key
*sk
= NULL
;
206 PKT_signature
*sig
= NULL
;
208 struct revocation_reason_info
*reason
= NULL
;
210 KEYDB_SEARCH_DESC desc
;
211 KBNODE keyblock
=NULL
,node
;
214 SK_LIST sk_list
=NULL
;
218 log_error(_("can't do this in batch mode\n"));
219 return G10ERR_GENERAL
;
222 afx
= new_armor_context ();
224 kdbhd
= keydb_new (0);
225 classify_user_id (uname
, &desc
);
226 rc
= desc
.mode
? keydb_search (kdbhd
, &desc
, 1) : G10ERR_INV_USER_ID
;
228 log_error (_("key \"%s\" not found: %s\n"),uname
, g10_errstr (rc
));
232 rc
= keydb_get_keyblock (kdbhd
, &keyblock
);
234 log_error (_("error reading keyblock: %s\n"), g10_errstr(rc
) );
238 /* To parse the revkeys */
239 merge_keys_and_selfsig(keyblock
);
241 /* get the key from the keyblock */
242 node
= find_kbnode( keyblock
, PKT_PUBLIC_KEY
);
246 pk
=node
->pkt
->pkt
.public_key
;
248 keyid_from_pk(pk
,keyid
);
252 rc
=build_sk_list(locusr
,&sk_list
,0,PUBKEY_USAGE_CERT
);
257 /* Are we a designated revoker for this key? */
259 if(!pk
->revkey
&& pk
->numrevkeys
)
262 for(i
=0;i
<pk
->numrevkeys
;i
++)
271 for(list
=sk_list
;list
;list
=list
->next
)
273 byte fpr
[MAX_FINGERPRINT_LEN
];
276 fingerprint_from_sk(list
->sk
,fpr
,&fprlen
);
278 /* Don't get involved with keys that don't have 160
283 if(memcmp(fpr
,pk
->revkey
[i
].fpr
,20)==0)
288 sk
=copy_secret_key(NULL
,list
->sk
);
294 sk
=xmalloc_secure_clear(sizeof(*sk
));
295 rc
=get_seckey_byfprint(sk
,pk
->revkey
[i
].fpr
,MAX_FINGERPRINT_LEN
);
298 /* We have the revocation key */
301 PKT_signature
*revkey
= NULL
;
305 print_pubkey_info (NULL
, pk
);
308 tty_printf (_("To be revoked by:\n"));
309 print_seckey_info (sk
);
311 if(pk
->revkey
[i
].class&0x40)
312 tty_printf(_("(This is a sensitive revocation key)\n"));
315 if( !cpr_get_answer_is_yes("gen_desig_revoke.okay",
316 _("Create a designated revocation certificate for this key? (y/N) ")))
319 /* get the reason for the revocation (this is always v4) */
320 reason
= ask_revocation_reason( 1, 0, 1 );
324 rc
= check_secret_key( sk
, 0 );
329 tty_printf(_("ASCII armored output forced.\n"));
331 if( (rc
= open_outfile( NULL
, 0, &out
)) )
335 afx
->hdrlines
= "Comment: A designated revocation certificate"
337 push_armor_filter (afx
, out
);
340 rc
= make_keysig_packet( &sig
, pk
, NULL
, NULL
, sk
, 0x20, 0,
342 revocation_reason_build_cb
, reason
);
344 log_error(_("make_keysig_packet failed: %s\n"), g10_errstr(rc
));
348 /* Spit out a minimal pk as well, since otherwise there is
349 no way to know which key to attach this revocation to.
350 Also include the direct key signature that contains
351 this revocation key. We're allowed to include
352 sensitive revocation keys along with a revocation, as
353 this may be the only time the recipient has seen it.
354 Note that this means that if we have multiple different
355 sensitive revocation keys in a given direct key
356 signature, we're going to include them all here. This
357 is annoying, but the good outweighs the bad, since
358 without including this a sensitive revoker can't really
359 do their job. People should not include multiple
360 sensitive revocation keys in one signature: 2440 says
361 "Note that it may be appropriate to isolate this
362 subpacket within a separate signature so that it is not
363 combined with other subpackets that need to be
370 signode
=find_next_kbnode(node
,PKT_SIGNATURE
);
376 if(keyid
[0]==signode
->pkt
->pkt
.signature
->keyid
[0] &&
377 keyid
[1]==signode
->pkt
->pkt
.signature
->keyid
[1] &&
378 IS_KEY_SIG(signode
->pkt
->pkt
.signature
))
382 for(j
=0;j
<signode
->pkt
->pkt
.signature
->numrevkeys
;j
++)
384 if(pk
->revkey
[i
].class==
385 signode
->pkt
->pkt
.signature
->revkey
[j
]->class &&
386 pk
->revkey
[i
].algid
==
387 signode
->pkt
->pkt
.signature
->revkey
[j
]->algid
&&
388 memcmp(pk
->revkey
[i
].fpr
,
389 signode
->pkt
->pkt
.signature
->revkey
[j
]->fpr
,
390 MAX_FINGERPRINT_LEN
)==0)
392 revkey
=signode
->pkt
->pkt
.signature
;
402 rc
=export_minimal_pk(out
,keyblock
,sig
,revkey
);
406 /* and issue a usage notice */
407 tty_printf(_("Revocation certificate created.\n"));
413 log_error(_("no revocation keys found for \"%s\"\n"),uname
);
417 free_public_key( pk
);
419 free_secret_key( sk
);
421 free_seckey_enc( sig
);
423 release_sk_list(sk_list
);
429 release_revocation_reason_info( reason
);
430 release_armor_context (afx
);
436 * Generate a revocation certificate for UNAME
439 gen_revoke( const char *uname
)
442 armor_filter_context_t
*afx
;
444 PKT_secret_key
*sk
; /* used as pointer into a kbnode */
445 PKT_public_key
*pk
= NULL
;
446 PKT_signature
*sig
= NULL
;
449 KBNODE keyblock
= NULL
, pub_keyblock
= NULL
;
452 struct revocation_reason_info
*reason
= NULL
;
453 KEYDB_SEARCH_DESC desc
;
457 log_error(_("can't do this in batch mode\n"));
458 return G10ERR_GENERAL
;
461 afx
= new_armor_context ();
464 /* search the userid:
465 * We don't want the whole getkey stuff here but the entire keyblock
467 kdbhd
= keydb_new (1);
468 classify_user_id (uname
, &desc
);
469 rc
= desc
.mode
? keydb_search (kdbhd
, &desc
, 1) : G10ERR_INV_USER_ID
;
472 log_error (_("secret key \"%s\" not found: %s\n"),
473 uname
, g10_errstr (rc
));
477 rc
= keydb_get_keyblock (kdbhd
, &keyblock
);
479 log_error (_("error reading keyblock: %s\n"), g10_errstr(rc
) );
483 /* get the keyid from the keyblock */
484 node
= find_kbnode( keyblock
, PKT_SECRET_KEY
);
488 /* fixme: should make a function out of this stuff,
489 * it's used all over the source */
490 sk
= node
->pkt
->pkt
.secret_key
;
491 keyid_from_sk( sk
, sk_keyid
);
492 print_seckey_info (sk
);
494 pk
= xmalloc_clear( sizeof *pk
);
496 /* FIXME: We should get the public key direct from the secret one */
498 pub_keyblock
=get_pubkeyblock(sk_keyid
);
501 log_error(_("no corresponding public key: %s\n"), g10_errstr(rc
) );
505 node
=find_kbnode(pub_keyblock
,PKT_PUBLIC_KEY
);
509 pk
=node
->pkt
->pkt
.public_key
;
511 if( cmp_public_secret_key( pk
, sk
) ) {
512 log_error(_("public key does not match secret key!\n") );
518 if( !cpr_get_answer_is_yes("gen_revoke.okay",
519 _("Create a revocation certificate for this key? (y/N) ")) )
525 if(sk
->version
>=4 || opt
.force_v4_certs
) {
526 /* get the reason for the revocation */
527 reason
= ask_revocation_reason( 1, 0, 1 );
528 if( !reason
) { /* user decided to cancel */
534 switch( is_secret_key_protected( sk
) ) {
536 log_error(_("unknown protection algorithm\n"));
537 rc
= G10ERR_PUBKEY_ALGO
;
540 tty_printf (_("Secret parts of primary key are not available.\n"));
541 rc
= G10ERR_NO_SECKEY
;
544 tty_printf(_("NOTE: This key is not protected!\n"));
547 rc
= check_secret_key( sk
, 0 );
555 tty_printf(_("ASCII armored output forced.\n"));
557 if( (rc
= open_outfile( NULL
, 0, &out
)) )
561 afx
->hdrlines
= "Comment: A revocation certificate should follow\n";
562 push_armor_filter (afx
, out
);
565 rc
= make_keysig_packet( &sig
, pk
, NULL
, NULL
, sk
, 0x20, 0,
566 opt
.force_v4_certs
?4:0, 0, 0,
567 revocation_reason_build_cb
, reason
);
569 log_error(_("make_keysig_packet failed: %s\n"), g10_errstr(rc
));
573 if(PGP2
|| PGP6
|| PGP7
|| PGP8
)
575 /* Use a minimal pk for PGPx mode, since PGP can't import bare
576 revocation certificates. */
577 rc
=export_minimal_pk(out
,pub_keyblock
,sig
,NULL
);
584 pkt
.pkttype
= PKT_SIGNATURE
;
585 pkt
.pkt
.signature
= sig
;
587 rc
= build_packet( out
, &pkt
);
589 log_error(_("build_packet failed: %s\n"), g10_errstr(rc
) );
594 /* and issue a usage notice */
595 tty_printf(_("Revocation certificate created.\n\n"
596 "Please move it to a medium which you can hide away; if Mallory gets\n"
597 "access to this certificate he can use it to make your key unusable.\n"
598 "It is smart to print this certificate and store it away, just in case\n"
599 "your media become unreadable. But have some caution: The print system of\n"
600 "your machine might store the data and make it available to others!\n"));
604 free_seckey_enc( sig
);
605 release_kbnode( keyblock
);
606 release_kbnode( pub_keyblock
);
607 keydb_release (kdbhd
);
612 release_revocation_reason_info( reason
);
613 release_armor_context (afx
);
619 struct revocation_reason_info
*
620 ask_revocation_reason( int key_rev
, int cert_rev
, int hint
)
623 char *description
= NULL
;
624 struct revocation_reason_info
*reason
;
625 const char *text_0
= _("No reason specified");
626 const char *text_1
= _("Key has been compromised");
627 const char *text_2
= _("Key is superseded");
628 const char *text_3
= _("Key is no longer used");
629 const char *text_4
= _("User ID is no longer valid");
630 const char *code_text
= NULL
;
637 tty_printf(_("Please select the reason for the revocation:\n"));
638 tty_printf( " 0 = %s\n", text_0
);
640 tty_printf(" 1 = %s\n", text_1
);
642 tty_printf(" 2 = %s\n", text_2
);
644 tty_printf(" 3 = %s\n", text_3
);
646 tty_printf(" 4 = %s\n", text_4
);
647 tty_printf( " Q = %s\n", _("Cancel") );
649 tty_printf(_("(Probably you want to select %d here)\n"), hint
);
653 char *answer
= cpr_get("ask_revocation_reason.code",
654 _("Your decision? "));
655 trim_spaces( answer
);
657 if( *answer
== 'q' || *answer
== 'Q')
658 return NULL
; /* cancel */
659 if( hint
&& !*answer
)
661 else if(!digitp( answer
) )
667 code
= 0x00; /* no particular reason */
670 else if( key_rev
&& n
== 1 ) {
671 code
= 0x02; /* key has been compromised */
674 else if( key_rev
&& n
== 2 ) {
675 code
= 0x01; /* key is superseded */
678 else if( key_rev
&& n
== 3 ) {
679 code
= 0x03; /* key is no longer used */
682 else if( cert_rev
&& n
== 4 ) {
683 code
= 0x20; /* uid is no longer valid */
687 tty_printf(_("Invalid selection.\n"));
690 tty_printf(_("Enter an optional description; "
691 "end it with an empty line:\n") );
693 char *answer
= cpr_get("ask_revocation_reason.text", "> " );
694 trim_trailing_ws( answer
, strlen(answer
) );
702 char *p
= make_printable_string( answer
, strlen(answer
), 0 );
708 description
= xstrdup(answer
);
710 char *p
= xmalloc( strlen(description
) + strlen(answer
) + 2 );
711 strcpy(stpcpy(stpcpy( p
, description
),"\n"),answer
);
718 tty_printf(_("Reason for revocation: %s\n"), code_text
);
720 tty_printf(_("(No description given)\n") );
722 tty_printf("%s\n", description
);
724 } while( !cpr_get_answer_is_yes("ask_revocation_reason.okay",
725 _("Is this okay? (y/N) ")) );
727 reason
= xmalloc( sizeof *reason
);
729 reason
->desc
= description
;
734 release_revocation_reason_info( struct revocation_reason_info
*reason
)
737 xfree( reason
->desc
);