edit-key is now complete
[gnupg.git] / g10 / encode.c
1 /* encode.c - encode data
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 "iobuf.h"
32 #include "keydb.h"
33 #include "memory.h"
34 #include "util.h"
35 #include "main.h"
36 #include "filter.h"
37 #include "i18n.h"
38
39
40 static int encode_simple( const char *filename, int mode );
41 static int write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out );
42
43
44
45 /****************
46  * Encode FILENAME with only the symmetric cipher.  Take input from
47  * stdin if FILENAME is NULL.
48  */
49 int
50 encode_symmetric( const char *filename )
51 {
52     return encode_simple( filename, 1 );
53 }
54
55 /****************
56  * Encode FILENAME as a literal data packet only. Take input from
57  * stdin if FILENAME is NULL.
58  */
59 int
60 encode_store( const char *filename )
61 {
62     return encode_simple( filename, 0 );
63 }
64
65
66 static int
67 encode_simple( const char *filename, int mode )
68 {
69     IOBUF inp, out;
70     PACKET pkt;
71     PKT_plaintext *pt;
72     STRING2KEY *s2k = NULL;
73     int rc = 0;
74     u32 filesize;
75     cipher_filter_context_t cfx;
76     armor_filter_context_t afx;
77     compress_filter_context_t zfx;
78
79     memset( &cfx, 0, sizeof cfx);
80     memset( &afx, 0, sizeof afx);
81     memset( &zfx, 0, sizeof zfx);
82
83     /* prepare iobufs */
84     if( !(inp = iobuf_open(filename)) ) {
85         log_error(_("%s: can't open: %s\n"), filename? filename: "[stdin]",
86                                         strerror(errno) );
87         return G10ERR_OPEN_FILE;
88     }
89
90     cfx.dek = NULL;
91     if( mode ) {
92         s2k = m_alloc_clear( sizeof *s2k );
93         s2k->mode = opt.rfc1991? 0:1;
94         s2k->hash_algo = opt.def_digest_algo ? opt.def_digest_algo
95                                              : DEFAULT_DIGEST_ALGO;
96         cfx.dek = passphrase_to_dek( NULL, opt.def_cipher_algo, s2k, 2 );
97         if( !cfx.dek || !cfx.dek->keylen ) {
98             rc = G10ERR_PASSPHRASE;
99             m_free(cfx.dek);
100             m_free(s2k);
101             iobuf_close(inp);
102             log_error(_("error creating passphrase: %s\n"), g10_errstr(rc) );
103             return rc;
104         }
105     }
106
107     if( !(out = open_outfile( filename, opt.armor? 1:0 )) ) {
108         iobuf_close(inp);
109         m_free(cfx.dek);
110         m_free(s2k);
111         return G10ERR_CREATE_FILE;  /* or user said: do not overwrite */
112     }
113
114     if( opt.armor )
115         iobuf_push_filter( out, armor_filter, &afx );
116     else
117         write_comment( out, "#created by GNUPG v" VERSION " ("
118                                             PRINTABLE_OS_NAME ")");
119
120     if( s2k && !opt.rfc1991 ) {
121         PKT_symkey_enc *enc = m_alloc_clear( sizeof *enc );
122         enc->version = 4;
123         enc->cipher_algo = cfx.dek->algo;
124         enc->s2k = *s2k;
125         pkt.pkttype = PKT_SYMKEY_ENC;
126         pkt.pkt.symkey_enc = enc;
127         if( (rc = build_packet( out, &pkt )) )
128             log_error("build symkey packet failed: %s\n", g10_errstr(rc) );
129         m_free(enc);
130     }
131
132     /* setup the inner packet */
133     if( filename ) {
134         pt = m_alloc( sizeof *pt + strlen(filename) - 1 );
135         pt->namelen = strlen(filename);
136         memcpy(pt->name, filename, pt->namelen );
137         if( !(filesize = iobuf_get_filelength(inp)) )
138             log_info(_("%s: warning: empty file\n"), filename );
139     }
140     else { /* no filename */
141         pt = m_alloc( sizeof *pt - 1 );
142         pt->namelen = 0;
143         filesize = 0; /* stdin */
144     }
145     pt->timestamp = make_timestamp();
146     pt->mode = 'b';
147     pt->len = filesize;
148     pt->buf = inp;
149     pkt.pkttype = PKT_PLAINTEXT;
150     pkt.pkt.plaintext = pt;
151     cfx.datalen = filesize && !opt.compress ? calc_packet_length( &pkt ) : 0;
152
153     /* register the cipher filter */
154     if( mode )
155         iobuf_push_filter( out, cipher_filter, &cfx );
156     /* register the compress filter */
157     if( opt.compress )
158         iobuf_push_filter( out, compress_filter, &zfx );
159
160     /* do the work */
161     if( (rc = build_packet( out, &pkt )) )
162         log_error("build_packet failed: %s\n", g10_errstr(rc) );
163
164     /* finish the stuff */
165     iobuf_close(inp);
166     iobuf_close(out); /* fixme: check returncode */
167     pt->buf = NULL;
168     free_packet(&pkt);
169     m_free(cfx.dek);
170     m_free(s2k);
171     return rc;
172 }
173
174 /****************
175  * Encrypt the file with the given userids (or ask if none
176  * is supplied).
177  */
178 int
179 encode_crypt( const char *filename, STRLIST remusr )
180 {
181     IOBUF inp = NULL, out = NULL;
182     PACKET pkt;
183     PKT_plaintext *pt = NULL;
184     int rc = 0;
185     u32 filesize;
186     cipher_filter_context_t cfx;
187     armor_filter_context_t afx;
188     compress_filter_context_t zfx;
189     PK_LIST pk_list;
190
191     memset( &cfx, 0, sizeof cfx);
192     memset( &afx, 0, sizeof afx);
193     memset( &zfx, 0, sizeof zfx);
194
195     if( (rc=build_pk_list( remusr, &pk_list, PUBKEY_USAGE_ENC)) )
196         return rc;
197
198     /* prepare iobufs */
199     if( !(inp = iobuf_open(filename)) ) {
200         log_error(_("can't open %s: %s\n"), filename? filename: "[stdin]",
201                                         strerror(errno) );
202         rc = G10ERR_OPEN_FILE;
203         goto leave;
204     }
205     else if( opt.verbose )
206         log_info(_("reading from '%s'\n"), filename? filename: "[stdin]");
207
208     if( !(out = open_outfile( filename, opt.armor? 1:0 )) ) {
209         rc = G10ERR_CREATE_FILE;  /* or user said: do not overwrite */
210         goto leave;
211     }
212
213     if( opt.armor )
214         iobuf_push_filter( out, armor_filter, &afx );
215     else
216         write_comment( out, "#created by GNUPG v" VERSION " ("
217                                             PRINTABLE_OS_NAME ")");
218
219     /* create a session key */
220     cfx.dek = m_alloc_secure( sizeof *cfx.dek );
221     cfx.dek->algo = opt.def_cipher_algo;
222     make_session_key( cfx.dek );
223     if( DBG_CIPHER )
224         log_hexdump("DEK is: ", cfx.dek->key, cfx.dek->keylen );
225
226     rc = write_pubkey_enc_from_list( pk_list, cfx.dek, out );
227     if( rc  )
228         goto leave;
229
230     /* setup the inner packet */
231     if( filename ) {
232         pt = m_alloc( sizeof *pt + strlen(filename) - 1 );
233         pt->namelen = strlen(filename);
234         memcpy(pt->name, filename, pt->namelen );
235         if( !(filesize = iobuf_get_filelength(inp)) )
236             log_info(_("%s: warning: empty file\n"), filename );
237     }
238     else { /* no filename */
239         pt = m_alloc( sizeof *pt - 1 );
240         pt->namelen = 0;
241         filesize = 0; /* stdin */
242     }
243     pt->timestamp = make_timestamp();
244     pt->mode = 'b';
245     pt->len = filesize;
246     pt->new_ctb = !pt->len && !opt.rfc1991;
247     pt->buf = inp;
248     init_packet(&pkt);
249     pkt.pkttype = PKT_PLAINTEXT;
250     pkt.pkt.plaintext = pt;
251     cfx.datalen = filesize && !opt.compress? calc_packet_length( &pkt ) : 0;
252
253     /* register the cipher filter */
254     iobuf_push_filter( out, cipher_filter, &cfx );
255     /* register the compress filter */
256     if( opt.compress )
257         iobuf_push_filter( out, compress_filter, &zfx );
258
259     /* do the work */
260     if( (rc = build_packet( out, &pkt )) )
261         log_error("build_packet failed: %s\n", g10_errstr(rc) );
262
263     /* finish the stuff */
264   leave:
265     iobuf_close(inp);
266     if( rc )
267         iobuf_cancel(out);
268     else
269         iobuf_close(out); /* fixme: check returncode */
270     if( pt )
271         pt->buf = NULL;
272     free_packet(&pkt);
273     m_free(cfx.dek);
274     release_pk_list( pk_list );
275     return rc;
276 }
277
278
279 /****************
280  * Filter to do a complete public key encryption.
281  */
282 int
283 encrypt_filter( void *opaque, int control,
284                IOBUF a, byte *buf, size_t *ret_len)
285 {
286     size_t size = *ret_len;
287     encrypt_filter_context_t *efx = opaque;
288     int rc=0;
289
290     if( control == IOBUFCTRL_UNDERFLOW ) { /* decrypt */
291         BUG(); /* not used */
292     }
293     else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */
294         if( !efx->header_okay ) {
295             efx->cfx.dek = m_alloc_secure( sizeof *efx->cfx.dek );
296             efx->cfx.dek->algo = opt.def_cipher_algo;
297             make_session_key( efx->cfx.dek );
298             if( DBG_CIPHER )
299                 log_hexdump("DEK is: ",
300                              efx->cfx.dek->key, efx->cfx.dek->keylen );
301
302             rc = write_pubkey_enc_from_list( efx->pk_list, efx->cfx.dek, a );
303             if( rc )
304                 return rc;
305
306             iobuf_push_filter( a, cipher_filter, &efx->cfx );
307
308             efx->header_okay = 1;
309         }
310         rc = iobuf_write( a, buf, size );
311
312     }
313     else if( control == IOBUFCTRL_FREE ) {
314     }
315     else if( control == IOBUFCTRL_DESC ) {
316         *(char**)buf = "encrypt_filter";
317     }
318     return rc;
319 }
320
321
322 /****************
323  * Write pubkey-enc packets from the list of PKs to OUT.
324  */
325 static int
326 write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out )
327 {
328     PACKET pkt;
329     PKT_public_key *pk;
330     PKT_pubkey_enc  *enc;
331     int rc;
332
333     for( ; pk_list; pk_list = pk_list->next ) {
334         MPI frame;
335
336         pk = pk_list->pk;
337         if( is_RSA(pk->pubkey_algo) )
338             do_not_use_RSA();
339         enc = m_alloc_clear( sizeof *enc );
340         enc->pubkey_algo = pk->pubkey_algo;
341         keyid_from_pk( pk, enc->keyid );
342         frame = encode_session_key( dek, pubkey_nbits( pk->pubkey_algo,
343                                                           pk->pkey ) );
344         rc = pubkey_encrypt( pk->pubkey_algo, enc->data, frame, pk->pkey );
345         mpi_free( frame );
346         if( rc )
347             log_error("pubkey_encrypt failed: %s\n", g10_errstr(rc) );
348         else {
349             if( opt.verbose ) {
350                 char *ustr = get_user_id_string( enc->keyid );
351                 log_info(_("%s encrypted for: %s\n"),
352                     pubkey_algo_to_string(enc->pubkey_algo), ustr );
353                 m_free(ustr);
354             }
355             /* and write it */
356             init_packet(&pkt);
357             pkt.pkttype = PKT_PUBKEY_ENC;
358             pkt.pkt.pubkey_enc = enc;
359             rc = build_packet( out, &pkt );
360             if( rc )
361                log_error("build_packet(pubkey_enc) failed: %s\n", g10_errstr(rc));
362         }
363         free_pubkey_enc(enc);
364         if( rc )
365             return rc;
366     }
367     return 0;
368 }
369