See ChangeLog: Sat Nov 13 17:44:23 CET 1999 Werner Koch
[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
68 static int
69 encode_simple( const char *filename, int mode )
70 {
71     IOBUF inp, out;
72     PACKET pkt;
73     PKT_plaintext *pt = NULL;
74     STRING2KEY *s2k = NULL;
75     int rc = 0;
76     u32 filesize;
77     cipher_filter_context_t cfx;
78     armor_filter_context_t afx;
79     compress_filter_context_t zfx;
80     text_filter_context_t tfx;
81     int do_compress = opt.compress && !opt.rfc1991;
82
83     memset( &cfx, 0, sizeof cfx);
84     memset( &afx, 0, sizeof afx);
85     memset( &zfx, 0, sizeof zfx);
86     memset( &tfx, 0, sizeof tfx);
87     init_packet(&pkt);
88
89     /* prepare iobufs */
90     if( !(inp = iobuf_open(filename)) ) {
91         log_error(_("%s: can't open: %s\n"), filename? filename: "[stdin]",
92                                         strerror(errno) );
93         return G10ERR_OPEN_FILE;
94     }
95
96     if( opt.textmode )
97         iobuf_push_filter( inp, text_filter, &tfx );
98
99     cfx.dek = NULL;
100     if( mode ) {
101         s2k = m_alloc_clear( sizeof *s2k );
102         s2k->mode = opt.rfc1991? 0:opt.s2k_mode;
103         s2k->hash_algo = opt.def_digest_algo ? opt.def_digest_algo
104                                              : opt.s2k_digest_algo;
105         cfx.dek = passphrase_to_dek( NULL, 0,
106                        opt.def_cipher_algo ? opt.def_cipher_algo
107                                            : opt.s2k_cipher_algo , s2k, 2 );
108         if( !cfx.dek || !cfx.dek->keylen ) {
109             rc = G10ERR_PASSPHRASE;
110             m_free(cfx.dek);
111             m_free(s2k);
112             iobuf_close(inp);
113             log_error(_("error creating passphrase: %s\n"), g10_errstr(rc) );
114             return rc;
115         }
116     }
117
118     if( (rc = open_outfile( filename, opt.armor? 1:0, &out )) ) {
119         iobuf_close(inp);
120         m_free(cfx.dek);
121         m_free(s2k);
122         return rc;
123     }
124
125     if( opt.armor )
126         iobuf_push_filter( out, armor_filter, &afx );
127   #ifdef ENABLE_COMMENT_PACKETS
128     else {
129         write_comment( out, "#created by GNUPG v" VERSION " ("
130                                             PRINTABLE_OS_NAME ")");
131         if( opt.comment_string )
132             write_comment( out, opt.comment_string );
133     }
134   #endif
135     if( s2k && !opt.rfc1991 ) {
136         PKT_symkey_enc *enc = m_alloc_clear( sizeof *enc );
137         enc->version = 4;
138         enc->cipher_algo = cfx.dek->algo;
139         enc->s2k = *s2k;
140         pkt.pkttype = PKT_SYMKEY_ENC;
141         pkt.pkt.symkey_enc = enc;
142         if( (rc = build_packet( out, &pkt )) )
143             log_error("build symkey packet failed: %s\n", g10_errstr(rc) );
144         m_free(enc);
145     }
146
147     if (!opt.no_literal) {
148         /* setup the inner packet */
149         if( filename || opt.set_filename ) {
150             char *s = make_basename( opt.set_filename ? opt.set_filename
151                                                       : filename );
152             pt = m_alloc( sizeof *pt + strlen(s) - 1 );
153             pt->namelen = strlen(s);
154             memcpy(pt->name, s, pt->namelen );
155             m_free(s);
156         }
157         else { /* no filename */
158             pt = m_alloc( sizeof *pt - 1 );
159             pt->namelen = 0;
160         }
161     }
162
163     /* pgp5 has problems to decrypt symmetrically encrypted data from
164      * GnuPG if the filelength is in the inner packet.  It works
165      * when only partial length headers are use.  Until we have
166      * tracked this problem down. We use this temporary fix
167      * (fixme: remove the && !mode )
168      */
169     if( filename && !opt.textmode && !mode ) {
170         if( !(filesize = iobuf_get_filelength(inp)) )
171             log_info(_("%s: WARNING: empty file\n"), filename );
172     }
173     else
174         filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */
175
176     if (!opt.no_literal) {
177         pt->timestamp = make_timestamp();
178         pt->mode = opt.textmode? 't' : 'b';
179         pt->len = filesize;
180         pt->new_ctb = !pt->len && !opt.rfc1991;
181         pt->buf = inp;
182         pkt.pkttype = PKT_PLAINTEXT;
183         pkt.pkt.plaintext = pt;
184         cfx.datalen = filesize && !do_compress ? calc_packet_length( &pkt ) : 0;
185     }
186     else
187         cfx.datalen = filesize && !do_compress ? filesize : 0;
188
189     /* register the cipher filter */
190     if( mode )
191         iobuf_push_filter( out, cipher_filter, &cfx );
192     /* register the compress filter */
193     if( do_compress )
194         iobuf_push_filter( out, compress_filter, &zfx );
195
196     /* do the work */
197     if (!opt.no_literal) {
198         if( (rc = build_packet( out, &pkt )) )
199             log_error("build_packet failed: %s\n", g10_errstr(rc) );
200     }
201     else {
202         /* user requested not to create a literal packet,
203          * so we copy the plain data */
204         byte copy_buffer[4096];
205         int  bytes_copied;
206         while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1)
207             if (iobuf_write(out, copy_buffer, bytes_copied) == -1) {
208                 rc = G10ERR_WRITE_FILE;
209                 log_error("copying input to output failed: %s\n", g10_errstr(rc) );
210                 break;
211             }
212         memset(copy_buffer, 0, 4096); /* burn buffer */
213     }
214
215     /* finish the stuff */
216     iobuf_close(inp);
217     if (rc)
218         iobuf_cancel(out);
219     else
220         iobuf_close(out); /* fixme: check returncode */
221     if (pt)
222         pt->buf = NULL;
223     free_packet(&pkt);
224     m_free(cfx.dek);
225     m_free(s2k);
226     return rc;
227 }
228
229 /****************
230  * Encrypt the file with the given userids (or ask if none
231  * is supplied).
232  */
233 int
234 encode_crypt( const char *filename, STRLIST remusr )
235 {
236     IOBUF inp = NULL, out = NULL;
237     PACKET pkt;
238     PKT_plaintext *pt = NULL;
239     int rc = 0;
240     u32 filesize;
241     cipher_filter_context_t cfx;
242     armor_filter_context_t afx;
243     compress_filter_context_t zfx;
244     text_filter_context_t tfx;
245     PK_LIST pk_list;
246     int do_compress = opt.compress && !opt.rfc1991;
247
248
249     memset( &cfx, 0, sizeof cfx);
250     memset( &afx, 0, sizeof afx);
251     memset( &zfx, 0, sizeof zfx);
252     memset( &tfx, 0, sizeof tfx);
253     init_packet(&pkt);
254
255     if( (rc=build_pk_list( remusr, &pk_list, GCRY_PK_USAGE_ENCR)) )
256         return rc;
257
258     /* prepare iobufs */
259     if( !(inp = iobuf_open(filename)) ) {
260         log_error(_("can't open %s: %s\n"), filename? filename: "[stdin]",
261                                         strerror(errno) );
262         rc = G10ERR_OPEN_FILE;
263         goto leave;
264     }
265     else if( opt.verbose )
266         log_info(_("reading from `%s'\n"), filename? filename: "[stdin]");
267
268     if( opt.textmode )
269         iobuf_push_filter( inp, text_filter, &tfx );
270
271     if( (rc = open_outfile( filename, opt.armor? 1:0, &out )) )
272         goto leave;
273
274
275     if( opt.armor )
276         iobuf_push_filter( out, armor_filter, &afx );
277   #ifdef ENABLE_COMMENT_PACKETS
278     else {
279         write_comment( out, "#created by GNUPG v" VERSION " ("
280                                             PRINTABLE_OS_NAME ")");
281         if( opt.comment_string )
282             write_comment( out, opt.comment_string );
283     }
284   #endif
285     /* create a session key */
286     cfx.dek = m_alloc_secure( sizeof *cfx.dek );
287     if( !opt.def_cipher_algo ) { /* try to get it from the prefs */
288         cfx.dek->algo = select_algo_from_prefs( pk_list, PREFTYPE_SYM );
289         if( cfx.dek->algo == -1 )
290             cfx.dek->algo = DEFAULT_CIPHER_ALGO;
291     }
292     else
293         cfx.dek->algo = opt.def_cipher_algo;
294     make_session_key( cfx.dek );
295     if( DBG_CIPHER )
296         log_hexdump("DEK is: ", cfx.dek->key, cfx.dek->keylen );
297
298     rc = write_pubkey_enc_from_list( pk_list, cfx.dek, out );
299     if( rc  )
300         goto leave;
301
302     if (!opt.no_literal) {
303         /* setup the inner packet */
304         if( filename || opt.set_filename ) {
305             char *s = make_basename( opt.set_filename ? opt.set_filename : filename );
306             pt = m_alloc( sizeof *pt + strlen(s) - 1 );
307             pt->namelen = strlen(s);
308             memcpy(pt->name, s, pt->namelen );
309             m_free(s);
310         }
311         else { /* no filename */
312             pt = m_alloc( sizeof *pt - 1 );
313             pt->namelen = 0;
314         }
315     }
316
317     if( filename && !opt.textmode ) {
318         if( !(filesize = iobuf_get_filelength(inp)) )
319             log_info(_("%s: WARNING: empty file\n"), filename );
320     }
321     else
322         filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */
323
324     if (!opt.no_literal) {
325         pt->timestamp = make_timestamp();
326         pt->mode = opt.textmode ? 't' : 'b';
327         pt->len = filesize;
328         pt->new_ctb = !pt->len && !opt.rfc1991;
329         pt->buf = inp;
330         pkt.pkttype = PKT_PLAINTEXT;
331         pkt.pkt.plaintext = pt;
332         cfx.datalen = filesize && !do_compress? calc_packet_length( &pkt ) : 0;
333     }
334     else
335         cfx.datalen = filesize && !do_compress ? filesize : 0;
336
337     /* register the cipher filter */
338     iobuf_push_filter( out, cipher_filter, &cfx );
339
340     /* register the compress filter */
341     if( do_compress ) {
342         int compr_algo = select_algo_from_prefs( pk_list, PREFTYPE_COMPR );
343         if( !compr_algo )
344             ; /* don't use compression */
345         else {
346             if( compr_algo == 1 )
347                 zfx.algo = 1; /* default is 2 */
348             iobuf_push_filter( out, compress_filter, &zfx );
349         }
350     }
351
352     /* do the work */
353     if (!opt.no_literal) {
354         if( (rc = build_packet( out, &pkt )) )
355             log_error("build_packet failed: %s\n", g10_errstr(rc) );
356     }
357     else {
358         /* user requested not to create a literal packet, so we copy the plain data */
359         byte copy_buffer[4096];
360         int  bytes_copied;
361         while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1)
362             if (iobuf_write(out, copy_buffer, bytes_copied) == -1) {
363                 rc = G10ERR_WRITE_FILE;
364                 log_error("copying input to output failed: %s\n", g10_errstr(rc) );
365                 break;
366             }
367         memset(copy_buffer, 0, 4096); /* burn buffer */
368     }
369
370     /* finish the stuff */
371   leave:
372     iobuf_close(inp);
373     if( rc )
374         iobuf_cancel(out);
375     else
376         iobuf_close(out); /* fixme: check returncode */
377     if( pt )
378         pt->buf = NULL;
379     free_packet(&pkt);
380     m_free(cfx.dek);
381     release_pk_list( pk_list );
382     return rc;
383 }
384
385
386
387
388 /****************
389  * Filter to do a complete public key encryption.
390  */
391 int
392 encrypt_filter( void *opaque, int control,
393                IOBUF a, byte *buf, size_t *ret_len)
394 {
395     size_t size = *ret_len;
396     encrypt_filter_context_t *efx = opaque;
397     int rc=0;
398
399     if( control == IOBUFCTRL_UNDERFLOW ) { /* decrypt */
400         BUG(); /* not used */
401     }
402     else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */
403         if( !efx->header_okay ) {
404             efx->cfx.dek = m_alloc_secure( sizeof *efx->cfx.dek );
405
406             if( !opt.def_cipher_algo  ) { /* try to get it from the prefs */
407                 efx->cfx.dek->algo =
408                           select_algo_from_prefs( efx->pk_list, PREFTYPE_SYM );
409                 if( efx->cfx.dek->algo == -1 )
410                     efx->cfx.dek->algo = DEFAULT_CIPHER_ALGO;
411             }
412             else
413                 efx->cfx.dek->algo = opt.def_cipher_algo;
414             make_session_key( efx->cfx.dek );
415             if( DBG_CIPHER )
416                 log_hexdump("DEK is: ",
417                              efx->cfx.dek->key, efx->cfx.dek->keylen );
418
419             rc = write_pubkey_enc_from_list( efx->pk_list, efx->cfx.dek, a );
420             if( rc )
421                 return rc;
422
423             iobuf_push_filter( a, cipher_filter, &efx->cfx );
424
425             efx->header_okay = 1;
426         }
427         rc = iobuf_write( a, buf, size );
428
429     }
430     else if( control == IOBUFCTRL_FREE ) {
431     }
432     else if( control == IOBUFCTRL_DESC ) {
433         *(char**)buf = "encrypt_filter";
434     }
435     return rc;
436 }
437
438
439 /****************
440  * Write pubkey-enc packets from the list of PKs to OUT.
441  */
442 static int
443 write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out )
444 {
445     PACKET pkt;
446     PKT_public_key *pk;
447     PKT_pubkey_enc  *enc;
448     int rc;
449
450     for( ; pk_list; pk_list = pk_list->next ) {
451         MPI frame;
452
453         pk = pk_list->pk;
454
455         print_pubkey_algo_note( pk->pubkey_algo );
456         enc = m_alloc_clear( sizeof *enc );
457         enc->pubkey_algo = pk->pubkey_algo;
458         keyid_from_pk( pk, enc->keyid );
459         enc->throw_keyid = opt.throw_keyid;
460
461         /* Okay, what's going on: We have the session key somewhere in
462          * the structure DEK and want to encode this session key in
463          * an integer value of n bits.  pubkey_nbits gives us the
464          * number of bits we have to use.  We then encode the session
465          * key in some way and we get it back in the big intger value
466          * FRAME.  Then we use FRAME, the public key PK->PKEY and the
467          * algorithm number PK->PUBKEY_ALGO and pass it to pubkey_encrypt
468          * which returns the encrypted value in the array ENC->DATA.
469          * This array has a size which depends on the used algorithm
470          * (e.g. 2 for ElGamal).  We don't need frame anymore because we
471          * have everything now in enc->data which is the passed to
472          * build_packet()
473          */
474         frame = encode_session_key( dek, pubkey_nbits( pk->pubkey_algo,
475                                                           pk->pkey ) );
476         rc = pubkey_encrypt( pk->pubkey_algo, enc->data, frame, pk->pkey );
477         mpi_free( frame );
478         if( rc )
479             log_error("pubkey_encrypt failed: %s\n", g10_errstr(rc) );
480         else {
481             if( opt.verbose ) {
482                 char *ustr = get_user_id_string( enc->keyid );
483                 log_info(_("%s/%s encrypted for: %s\n"),
484                     gcry_pk_algo_name(enc->pubkey_algo),
485                     gcry_cipher_algo_name(dek->algo), ustr );
486                 m_free(ustr);
487             }
488             /* and write it */
489             init_packet(&pkt);
490             pkt.pkttype = PKT_PUBKEY_ENC;
491             pkt.pkt.pubkey_enc = enc;
492             rc = build_packet( out, &pkt );
493             if( rc )
494                log_error("build_packet(pubkey_enc) failed: %s\n", g10_errstr(rc));
495         }
496         free_pubkey_enc(enc);
497         if( rc )
498             return rc;
499     }
500     return 0;
501 }
502