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