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