2
* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
4
* This file is part of GnuPG.
6
* GnuPG is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* GnuPG is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
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_t 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 GPG_ERR_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"), gpg_strerror (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"), gpg_strerror (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"), gpg_strerror (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 %08lX incomplete\n"),(ulong)keyid[1]);
146
return GPG_ERR_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"), gpg_strerror (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"), gpg_strerror (rc) );
195
* Generate a revocation certificate for UNAME via a designated revoker
198
gen_desig_revoke( const char *uname )
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;
214
log_error(_("sorry, can't do this in batch mode\n"));
215
return GPG_ERR_GENERAL;
218
memset( &afx, 0, sizeof afx);
220
kdbhd = keydb_new (0);
221
classify_user_id (uname, &desc);
222
rc = desc.mode? keydb_search (kdbhd, &desc, 1) : GPG_ERR_INV_USER_ID;
224
log_error (_("key `%s' not found: %s\n"),uname, gpg_strerror (rc));
228
rc = keydb_get_keyblock (kdbhd, &keyblock );
230
log_error (_("error reading keyblock: %s\n"), gpg_strerror (rc) );
234
/* To parse the revkeys */
235
merge_keys_and_selfsig(keyblock);
237
/* get the key from the keyblock */
238
node = find_kbnode( keyblock, PKT_PUBLIC_KEY );
242
pk=node->pkt->pkt.public_key;
244
keyid_from_pk(pk,keyid);
246
/* Are we a designated revoker for this key? */
248
if(!pk->revkey && pk->numrevkeys)
251
for(i=0;i<pk->numrevkeys;i++)
256
sk=xcalloc (1,sizeof(*sk));
258
rc=get_seckey_byfprint(sk,pk->revkey[i].fpr,MAX_FINGERPRINT_LEN);
260
/* We have the revocation key */
263
PKT_signature *revkey = NULL;
267
print_pubkey_info (NULL, pk);
270
tty_printf (_("To be revoked by:\n"));
271
print_seckey_info (sk);
273
if(pk->revkey[i].class&0x40)
274
tty_printf(_("(This is a sensitive revocation key)\n"));
277
if( !cpr_get_answer_is_yes("gen_desig_revoke.okay",
278
_("Create a revocation certificate for this key? ")) )
281
/* get the reason for the revocation (this is always v4) */
282
reason = ask_revocation_reason( 1, 0, 1 );
286
rc = check_secret_key( sk, 0 );
291
tty_printf(_("ASCII armored output forced.\n"));
293
if( (rc = open_outfile( NULL, 0, &out )) )
297
afx.hdrlines = "Comment: A revocation certificate should follow\n";
298
iobuf_push_filter( out, armor_filter, &afx );
301
rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x20, 0,
303
revocation_reason_build_cb, reason );
305
log_error(_("make_keysig_packet failed: %s\n"), gpg_strerror (rc));
309
/* Spit out a minimal pk as well, since otherwise there is
310
no way to know which key to attach this revocation to.
311
Also include the direct key signature that contains
312
this revocation key. We're allowed to include
313
sensitive revocation keys along with a revocation, as
314
this may be the only time the recipient has seen it.
315
Note that this means that if we have multiple different
316
sensitive revocation keys in a given direct key
317
signature, we're going to include them all here. This
318
is annoying, but the good outweighs the bad, since
319
without including this a sensitive revoker can't really
320
do their job. People should not include multiple
321
sensitive revocation keys in one signature: 2440 says
322
"Note that it may be appropriate to isolate this
323
subpacket within a separate signature so that it is not
324
combined with other subpackets that need to be
331
signode=find_next_kbnode(node,PKT_SIGNATURE);
337
if(keyid[0]==signode->pkt->pkt.signature->keyid[0] &&
338
keyid[1]==signode->pkt->pkt.signature->keyid[1] &&
339
IS_KEY_SIG(signode->pkt->pkt.signature))
343
for(j=0;j<signode->pkt->pkt.signature->numrevkeys;j++)
345
if(pk->revkey[i].class==
346
signode->pkt->pkt.signature->revkey[j]->class &&
347
pk->revkey[i].algid==
348
signode->pkt->pkt.signature->revkey[j]->algid &&
349
memcmp(pk->revkey[i].fpr,
350
signode->pkt->pkt.signature->revkey[j]->fpr,
351
MAX_FINGERPRINT_LEN)==0)
353
revkey=signode->pkt->pkt.signature;
363
rc=export_minimal_pk(out,keyblock,sig,revkey);
367
/* and issue a usage notice */
368
tty_printf(_("Revocation certificate created.\n"));
374
log_error(_("no revocation keys found for `%s'\n"),uname);
378
free_public_key( pk );
380
free_secret_key( sk );
382
free_seckey_enc( sig );
388
release_revocation_reason_info( reason );
394
* Generate a revocation certificate for UNAME
397
gen_revoke( const char *uname )
400
armor_filter_context_t afx;
402
PKT_secret_key *sk; /* used as pointer into a kbnode */
403
PKT_public_key *pk = NULL;
404
PKT_signature *sig = NULL;
407
KBNODE keyblock = NULL, pub_keyblock = NULL;
410
struct revocation_reason_info *reason = NULL;
411
KEYDB_SEARCH_DESC desc;
414
log_error(_("sorry, can't do this in batch mode\n"));
415
return GPG_ERR_GENERAL;
418
memset( &afx, 0, sizeof afx);
421
/* search the userid:
422
* We don't want the whole getkey stuff here but the entire keyblock
424
kdbhd = keydb_new (1);
425
classify_user_id (uname, &desc);
426
rc = desc.mode? keydb_search (kdbhd, &desc, 1) : GPG_ERR_INV_USER_ID;
428
log_error (_("secret key `%s' not found: %s\n"),
429
uname, gpg_strerror (rc));
433
rc = keydb_get_keyblock (kdbhd, &keyblock );
435
log_error (_("error reading keyblock: %s\n"), gpg_strerror (rc) );
439
/* get the keyid from the keyblock */
440
node = find_kbnode( keyblock, PKT_SECRET_KEY );
444
/* fixme: should make a function out of this stuff,
445
* it's used all over the source */
446
sk = node->pkt->pkt.secret_key;
447
keyid_from_sk( sk, sk_keyid );
448
print_seckey_info (sk);
450
pk = xcalloc (1, sizeof *pk );
452
/* FIXME: We should get the public key direct from the secret one */
454
pub_keyblock=get_pubkeyblock(sk_keyid);
457
log_error(_("no corresponding public key: %s\n"), gpg_strerror (rc) );
461
node=find_kbnode(pub_keyblock,PKT_PUBLIC_KEY);
465
pk=node->pkt->pkt.public_key;
467
if( cmp_public_secret_key( pk, sk ) ) {
468
log_error(_("public key does not match secret key!\n") );
469
rc = GPG_ERR_GENERAL;
474
if( !cpr_get_answer_is_yes("gen_revoke.okay",
475
_("Create a revocation certificate for this key? ")) ){
480
if(sk->version>=4 || opt.force_v4_certs) {
481
/* get the reason for the revocation */
482
reason = ask_revocation_reason( 1, 0, 1 );
483
if( !reason ) { /* user decided to cancel */
489
switch( is_secret_key_protected( sk ) ) {
491
log_error(_("unknown protection algorithm\n"));
492
rc = GPG_ERR_PUBKEY_ALGO;
495
tty_printf(_("NOTE: This key is not protected!\n"));
498
rc = check_secret_key( sk, 0 );
506
tty_printf(_("ASCII armored output forced.\n"));
508
if( (rc = open_outfile( NULL, 0, &out )) )
512
afx.hdrlines = "Comment: A revocation certificate should follow\n";
513
iobuf_push_filter( out, armor_filter, &afx );
516
rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x20, 0,
517
opt.force_v4_certs?4:0, 0, 0,
518
revocation_reason_build_cb, reason );
520
log_error(_("make_keysig_packet failed: %s\n"), gpg_strerror (rc));
524
if(PGP2 || PGP6 || PGP7 || PGP8)
526
/* Use a minimal pk for PGPx mode, since PGP can't import bare
527
revocation certificates. */
528
rc=export_minimal_pk(out,pub_keyblock,sig,NULL);
535
pkt.pkttype = PKT_SIGNATURE;
536
pkt.pkt.signature = sig;
538
rc = build_packet( out, &pkt );
540
log_error(_("build_packet failed: %s\n"), gpg_strerror (rc) );
545
/* and issue a usage notice */
546
tty_printf(_("Revocation certificate created.\n\n"
547
"Please move it to a medium which you can hide away; if Mallory gets\n"
548
"access to this certificate he can use it to make your key unusable.\n"
549
"It is smart to print this certificate and store it away, just in case\n"
550
"your media become unreadable. But have some caution: The print system of\n"
551
"your machine might store the data and make it available to others!\n"));
555
free_seckey_enc( sig );
556
release_kbnode( keyblock );
557
release_kbnode( pub_keyblock );
558
keydb_release (kdbhd);
563
release_revocation_reason_info( reason );
569
struct revocation_reason_info *
570
ask_revocation_reason( int key_rev, int cert_rev, int hint )
573
char *description = NULL;
574
struct revocation_reason_info *reason;
575
const char *text_0 = _("No reason specified");
576
const char *text_1 = _("Key has been compromised");
577
const char *text_2 = _("Key is superseded");
578
const char *text_3 = _("Key is no longer used");
579
const char *text_4 = _("User ID is no longer valid");
580
const char *code_text = NULL;
587
tty_printf(_("Please select the reason for the revocation:\n"));
588
tty_printf( " 0 = %s\n", text_0 );
590
tty_printf(" 1 = %s\n", text_1 );
592
tty_printf(" 2 = %s\n", text_2 );
594
tty_printf(" 3 = %s\n", text_3 );
596
tty_printf(" 4 = %s\n", text_4 );
597
tty_printf( " Q = %s\n", _("Cancel") );
599
tty_printf(_("(Probably you want to select %d here)\n"), hint );
603
char *answer = cpr_get("ask_revocation_reason.code",
604
_("Your decision? "));
605
trim_spaces( answer );
607
if( *answer == 'q' || *answer == 'Q')
608
return NULL; /* cancel */
609
if( hint && !*answer )
611
else if(!digitp( answer ) )
617
code = 0x00; /* no particular reason */
620
else if( key_rev && n == 1 ) {
621
code = 0x02; /* key has been compromised */
624
else if( key_rev && n == 2 ) {
625
code = 0x01; /* key is superseded */
628
else if( key_rev && n == 3 ) {
629
code = 0x03; /* key is no longer used */
632
else if( cert_rev && n == 4 ) {
633
code = 0x20; /* uid is no longer valid */
637
tty_printf(_("Invalid selection.\n"));
640
tty_printf(_("Enter an optional description; "
641
"end it with an empty line:\n") );
643
char *answer = cpr_get("ask_revocation_reason.text", "> " );
644
trim_trailing_ws( answer, strlen(answer) );
652
char *p = make_printable_string( answer, strlen(answer), 0 );
658
description = xstrdup (answer);
660
char *p = xmalloc ( strlen(description) + strlen(answer) + 2 );
661
strcpy(stpcpy(stpcpy( p, description),"\n"),answer);
668
tty_printf(_("Reason for revocation: %s\n"), code_text );
670
tty_printf(_("(No description given)\n") );
672
tty_printf("%s\n", description );
674
} while( !cpr_get_answer_is_yes("ask_revocation_reason.okay",
675
_("Is this okay? ")) );
677
reason = xmalloc ( sizeof *reason );
679
reason->desc = description;
684
release_revocation_reason_info( struct revocation_reason_info *reason )
687
xfree ( reason->desc );