fingerprints and self signatures added
[gnupg.git] / g10 / g10.c
1 /* g10.c - The G10 re-install utility
2  *      Copyright (c) 1997 by Werner Koch (dd9jn)
3  *
4  * This file is part of G10.
5  *
6  * G10 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  * G10 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 <unistd.h>
25
26 #include "packet.h"
27 #include "iobuf.h"
28 #include "memory.h"
29 #include "util.h"
30 #include "main.h"
31 #include "options.h"
32 #include "keydb.h"
33 #include "mpi.h"
34 #include "cipher.h"
35 #include "filter.h"
36
37 static void do_test(int);
38
39 const char *
40 strusage( int level )
41 {
42     const char *p;
43     switch( level ) {
44       case 10:
45       case 0:   p = "g10 - v" VERSION "; "
46                     "Copyright 1997 Werner Koch (dd9jn)\n" ; break;
47       case 13:  p = "g10"; break;
48       case 14:  p = VERSION; break;
49       case 1:
50       case 11:  p = "Usage: g10 [options] [files] (-h for help)";
51                 break;
52       case 2:
53       case 12:  p =
54     "Syntax: g10 [options] [files]\n"
55     "sign, check, encrypt or decrypt\n"
56     "default operation depends on the input data\n"; break;
57
58       case 26:
59         p = "Please report bugs to <g10-bugs@isil.d.shuttle.de>.\n";
60         break;
61
62       case 30: p = ""
63   #ifndef HAVE_ZLIB_H
64     "   NOTE: This version is compiled without ZLIB support;\n"
65     "         you are not able to process compresssed data!\n"
66   #endif
67   #ifdef HAVE_RSA_CIPHER
68     "WARNING: This version has RSA support! Your are not allowed to\n"
69     "         use it inside the Unites States before Sep 30, 2000!\n"
70   #endif
71         ;
72         break;
73       default:  p = default_strusage(level);
74     }
75     return p;
76 }
77
78 static void
79 set_debug(void)
80 {
81     if( opt.debug & DBG_MEMORY_VALUE )
82         memory_debug_mode = 1;
83     if( opt.debug & DBG_MEMSTAT_VALUE )
84         memory_stat_debug_mode = 1;
85     if( opt.debug & DBG_MPI_VALUE )
86         mpi_debug_mode = 1;
87     if( opt.debug & DBG_CIPHER_VALUE )
88         cipher_debug_mode = 1;
89     if( opt.debug & DBG_IOBUF_VALUE )
90         iobuf_debug_mode = 1;
91 }
92
93
94
95 int
96 main( int argc, char **argv )
97 {
98     static ARGPARSE_OPTS opts[] = {
99     { 'a', "armor",     0, "create ascii armored output"},
100     { 'v', "verbose",   0, "verbose" },
101     { 'z', NULL,        1, "set compress level (0 disables)" },
102     { 'n', "dry-run",   0, "don't make any changes" },
103     { 'c', "symmetric", 0, "do only a symmetric encryption" },
104     { 'o', "output",    2, "use as output file" },
105     { 500, "batch",     0, "batch mode: never ask" },
106     { 501, "yes",       0, "assume yes on most questions"},
107     { 502, "no",        0, "assume no on most questions"},
108     { 503, "gen-key",   0, "generate a new key pair" },
109     { 504, "add-key",   0, "add key to the public keyring" },
110     { 505, "delete-key",0, "remove key from public keyring" },
111     { 506, "sign-key"  ,0, "make a signature on a key in the keyring" },
112     { 507, "store",     0, "store only" },
113     { 508, "check-key" ,0, "check signatures on a key in the keyring" },
114     { 509, "keyring"   ,2, "add this keyring to the list of keyrings" },
115     { 's', "sign",      0, "make a signature"},
116     { 'b', "detach-sign", 0, "make a detached signature"},
117     { 'e', "encrypt",   0, "encrypt data" },
118     { 'd', "decrypt",   0, "decrypt data (default)" },
119   /*{ 'c', "check",     0, "check a signature (default)" }, */
120     { 'l', "local-user",2, "use this user-id to sign or decrypt" },
121     { 'r', "remote-user", 2, "use this user-id for encryption" },
122     { 510, "debug"     ,4|16, "set debugging flags" },
123     { 511, "debug-all" ,0, "enable full debugging"},
124     { 512, "cache-all" ,0, "hold everything in memory"},
125     { 513, "gen-prime" , 1, "\rgenerate a prime of length n" },
126     { 514, "test"      , 0, "\rdevelopment usage" },
127     { 515, "change-passphrase", 0, "change the passphrase of your secret keyring"},
128     { 515, "fingerprint", 0, "show the fingerprints"},
129     {0} };
130     ARGPARSE_ARGS pargs = { &argc, &argv, 0 };
131     IOBUF a;
132     int rc;
133     enum { aNull, aSym, aStore, aEncr, aPrimegen, aKeygen, aSign, aSignEncr,
134            aTest,
135     } action = aNull;
136     const char *fname, *fname_print;
137     STRLIST sl, remusr= NULL, locusr=NULL;
138     int nrings=0;
139     armor_filter_context_t afx;
140     const char *s;
141     int detached_sig = 0;
142
143     opt.compress = -1; /* defaults to default compression level */
144     while( arg_parse( &pargs, opts) ) {
145         switch( pargs.r_opt ) {
146           case 'v': opt.verbose++;
147                     opt.list_sigs=1;
148                     break;
149           case 'z':
150             opt.compress = pargs.r.ret_int;
151             break;
152           case 'a': opt.armor = 1; break;
153           case 'c': action = aSym; break;
154           case 'o': opt.outfile = pargs.r.ret_str;
155                     if( opt.outfile[0] == '-' && !opt.outfile[1] )
156                         opt.outfile_is_stdout = 1;
157                     break;
158           case 'e': action = action == aSign? aSignEncr : aEncr; break;
159           case 'b': detached_sig = 1;
160                /* fall trough */
161           case 's': action = action == aEncr? aSignEncr : aSign;  break;
162           case 'l': /* store the local users */
163             sl = m_alloc( sizeof *sl + strlen(pargs.r.ret_str));
164             strcpy(sl->d, pargs.r.ret_str);
165             sl->next = locusr;
166             locusr = sl;
167             break;
168           case 'r': /* store the remote users */
169             sl = m_alloc( sizeof *sl + strlen(pargs.r.ret_str));
170             strcpy(sl->d, pargs.r.ret_str);
171             sl->next = remusr;
172             remusr = sl;
173             break;
174           case 500: opt.batch = 1; break;
175           case 501: opt.answer_yes = 1; break;
176           case 502: opt.answer_no = 1; break;
177           case 503: action = aKeygen; break;
178           case 507: action = aStore; break;
179           case 508: opt.check_sigs = 1; opt.list_sigs = 1; break;
180           case 509: add_keyring(pargs.r.ret_str); nrings++; break;
181           case 510: opt.debug |= pargs.r.ret_ulong; break;
182           case 511: opt.debug = ~0; break;
183           case 512: opt.cache_all = 1; break;
184           case 513: action = aPrimegen; break;
185           case 514: action = aTest; break;
186           case 515: opt.fingerprint = 1; break;
187           default : pargs.err = 2; break;
188         }
189     }
190     set_debug();
191     if( opt.verbose > 1 )
192         set_packet_list_mode(1);
193     if( !opt.batch && isatty(fileno(stdin)) ) {
194         if( *(s=strusage(10))  )
195             fputs(s, stderr);
196         if( *(s=strusage(30))  )
197             fputs(s, stderr);
198     }
199
200     if( !nrings ) { /* add default rings */
201         add_keyring("../keys/ring.pgp");
202         add_keyring("../keys/pubring.g10");
203     }
204
205     if( argc ) {
206         fname_print = fname = *argv;
207     }
208     else {
209         fname_print = "[stdin]";
210         fname = NULL;
211     }
212
213     switch( action ) {
214       case aStore: /* only store the file */
215         if( argc > 1 )
216             usage(1);
217         if( (rc = encode_store(fname)) )
218             log_error("encode_store('%s'): %s\n",
219                                     fname_print, g10_errstr(rc) );
220         break;
221
222       case aSym: /* encrypt the given file only with the symmetric cipher */
223         if( argc > 1 )
224             usage(1);
225         if( (rc = encode_symmetric(fname)) )
226             log_error("encode_symmetric('%s'): %s\n", fname_print, g10_errstr(rc) );
227         break;
228
229       case aEncr: /* encrypt the given file */
230         if( argc > 1 )
231             usage(1);
232         if( (rc = encode_crypt(fname,remusr)) )
233             log_error("encode_crypt('%s'): %s\n", fname_print, g10_errstr(rc) );
234         break;
235
236       case aSign: /* sign the given file */
237         if( argc > 1 )
238             usage(1);
239         if( (rc = sign_file(fname, detached_sig, locusr)) )
240             log_error("sign_file('%s'): %s\n", fname_print, g10_errstr(rc) );
241         break;
242
243       case aSignEncr: /* sign and encrypt the given file */
244         usage(1);  /* FIXME */
245         break;
246
247       case aPrimegen:
248         if( argc )
249             usage(1);
250         mpi_print( stdout, generate_public_prime( pargs.r.ret_int ), 1);
251         putchar('\n');
252         break;
253
254       case aKeygen: /* generate a key (interactive) */
255         if( argc )
256             usage(1);
257         generate_keypair();
258         break;
259
260       case aTest: do_test( atoi(*argv) ); break;
261
262       default:
263         if( argc > 1 )
264             usage(1);
265         if( !(a = iobuf_open(fname)) )
266             log_fatal("can't open '%s'\n", fname_print);
267         /* push the armor filter, so it can peek at the input data */
268         memset( &afx, 0, sizeof afx);
269         iobuf_push_filter( a, armor_filter, &afx );
270         proc_packets( a );
271         iobuf_close(a);
272         break;
273     }
274
275     /* cleanup */
276     FREE_STRLIST(remusr);
277     FREE_STRLIST(locusr);
278     return 0;
279 }
280
281
282
283 static void
284 do_test(int times)
285 {
286     MPI t = mpi_alloc( 50 );
287     MPI m = mpi_alloc( 50 );
288     MPI a = mpi_alloc( 50 );
289     MPI b = mpi_alloc( 50 );
290     MPI p = mpi_alloc( 50 );
291     MPI x = mpi_alloc( 50 );
292
293     /* output = b/(a^x) mod p */
294     log_debug("invm %d times ", times);
295     for( ; times > 0; times -- ) {
296         mpi_fromstr(a, "0xef45678343589854354a4545545454554545455"
297                        "aaaaaaaaaaaaa44444fffdecb33434343443331" );
298         mpi_fromstr(b, "0x8765765589854354a4545545454554545455"
299                        "aaaaaaa466577778decb36666343443331" );
300         mpi_invm( t, a, b );
301         fputc('.', stderr); fflush(stderr);
302     }
303
304
305     m_check(NULL);
306
307 }
308
309