add salted and iterated mode
[gnupg.git] / g10 / revoke.c
1 /* revoke.c
2  *      Copyright (C) 1998 Free Software Foundation, Inc.
3  *
4  * This file is part of GNUPG.
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <assert.h>
27
28 #include "options.h"
29 #include "packet.h"
30 #include "errors.h"
31 #include "keydb.h"
32 #include "memory.h"
33 #include "util.h"
34 #include "main.h"
35 #include "ttyio.h"
36
37
38 /****************
39  * Generate a revocation certificate for UNAME
40  */
41 int
42 gen_revoke( const char *uname )
43 {
44     int rc = 0;
45     armor_filter_context_t afx;
46     compress_filter_context_t zfx;
47     PACKET pkt;
48     PKT_secret_key *sk; /* used as pointer into a kbnode */
49     PKT_public_key *pk = NULL;
50     PKT_signature *sig = NULL;
51     u32 sk_keyid[2];
52     IOBUF out = NULL;
53     KBNODE keyblock = NULL;
54     KBNODE node;
55     KBPOS kbpos;
56     char *answer;
57     int yes;
58
59     if( opt.batch ) {
60         log_error("sorry, can't do this in batch mode\n");
61         return G10ERR_GENERAL;
62     }
63
64
65     memset( &afx, 0, sizeof afx);
66     memset( &zfx, 0, sizeof zfx);
67     init_packet( &pkt );
68
69
70     /* search the userid */
71     rc = find_secret_keyblock_byname( &kbpos, uname );
72     if( rc ) {
73         log_error("secret key for user '%s' not found\n", uname );
74         goto leave;
75     }
76
77     /* read the keyblock */
78     rc = read_keyblock( &kbpos, &keyblock );
79     if( rc ) {
80         log_error("error reading the certificate: %s\n", g10_errstr(rc) );
81         goto leave;
82     }
83
84     /* get the keyid from the keyblock */
85     node = find_kbnode( keyblock, PKT_SECRET_KEY );
86     if( !node ) { /* maybe better to use log_bug ? */
87         log_error("Oops; secret key not found anymore!\n");
88         rc = G10ERR_GENERAL;
89         goto leave;
90     }
91
92     /* fixme: should make a function out of this stuff,
93      * it's used all over the source */
94     sk = node->pkt->pkt.secret_key;
95     keyid_from_sk( sk, sk_keyid );
96     tty_printf("\nsec  %4u%c/%08lX %s   ",
97               nbits_from_sk( sk ),
98               pubkey_letter( sk->pubkey_algo ),
99               sk_keyid[1], datestr_from_sk(sk) );
100     {
101         size_t n;
102         char *p = get_user_id( sk_keyid, &n );
103         tty_print_string( p, n );
104         m_free(p);
105         tty_printf("\n");
106     }
107     pk = m_alloc_clear( sizeof *pk );
108     rc = get_pubkey( pk, sk_keyid );
109     if( rc ) {
110         log_error("no corresponding public key: %s\n", g10_errstr(rc) );
111         goto leave;
112     }
113     if( cmp_public_secret_key( pk, sk ) ) {
114         log_error("public key does not match secret key!\n" );
115         rc = G10ERR_GENERAL;
116         goto leave;
117     }
118
119     tty_printf("\n");
120     answer = tty_get("Create a revocation certificate for this key? ");
121     tty_kill_prompt();
122     yes = answer_is_yes(answer);
123     m_free(answer);
124     if( !yes ) {
125         rc = 0;
126         goto leave;
127     }
128
129     switch( is_secret_key_protected( sk ) ) {
130       case -1:
131         log_error("unknown protection algorithm\n");
132         rc = G10ERR_PUBKEY_ALGO;
133         break;
134       case 0:
135         tty_printf("Warning: This key is not protected!\n");
136         break;
137       default:
138         rc = check_secret_key( sk );
139         break;
140     }
141     if( rc )
142         goto leave;
143
144
145     if( !opt.armor )
146         tty_printf("ASCII armored output forced.\n");
147
148     if( !(out = open_outfile( NULL, 0 )) ) {
149         rc = G10ERR_CREATE_FILE;
150         goto leave;
151     }
152
153     afx.what = 1;
154     afx.hdrlines = "Comment: A revocation certificate should follow\n";
155     iobuf_push_filter( out, armor_filter, &afx );
156     if( opt.compress )
157         iobuf_push_filter( out, compress_filter, &zfx );
158
159
160     /* create it */
161     rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x20, 0, NULL, NULL);
162     if( rc ) {
163         log_error("make_keysig_packet failed: %s\n", g10_errstr(rc));
164         goto leave;
165     }
166     init_packet( &pkt );
167     pkt.pkttype = PKT_SIGNATURE;
168     pkt.pkt.signature = sig;
169
170     rc = build_packet( out, &pkt );
171     if( rc ) {
172         log_error("build_packet failed: %s\n", g10_errstr(rc) );
173         goto leave;
174     }
175
176     /* and issue a usage notice */
177     tty_printf("Revocation certificate created.\n\n"
178 "Please move it to a medium which you can hide away; if Mallory gets\n"
179 "access to this certificate he can use it to make your key unusable.\n"
180 "It is smart to print this certificate and store it away, just in case\n"
181 "your media become unreadable.  But have some caution:  The print system of\n"
182 "your machine might store the data and make it available to others!\n");
183
184
185
186   leave:
187     if( pk )
188         free_public_key( pk );
189     if( sig )
190         free_seckey_enc( sig );
191     release_kbnode( keyblock );
192     if( rc )
193         iobuf_cancel(out);
194     else
195         iobuf_close(out);
196     return rc;
197 }
198
199