* encode.c (encode_simple), passphrase.c (passphrase_to_dek), sign.c
[gnupg.git] / g10 / encode.c
1 /* encode.c - encode data
2  * Copyright (C) 1998, 1999, 2000, 2001, 2002 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 #include "status.h"
40
41 static int encode_simple( const char *filename, int mode, int compat );
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     int compat = 1;
54
55 #if 0    
56     /* We don't want to use it because older gnupg version can't
57        handle it and we can presume that a lot of scripts are running
58        with the expert mode set.  Some time in the future we might
59        want to allow for it. */
60     if ( opt.expert )
61         compat = 0; /* PGP knows how to handle this mode. */
62 #endif
63     return encode_simple( filename, 1, compat );
64 }
65
66 /****************
67  * Encode FILENAME as a literal data packet only. Take input from
68  * stdin if FILENAME is NULL.
69  */
70 int
71 encode_store( const char *filename )
72 {
73     return encode_simple( filename, 0, 1 );
74 }
75
76 static void
77 encode_sesskey( DEK *dek, DEK **ret_dek, byte *enckey )
78 {
79     CIPHER_HANDLE hd;
80     DEK *c;
81     byte buf[33];
82
83     assert ( dek->keylen < 32 );
84     
85     c = m_alloc_clear( sizeof *c );
86     c->keylen = dek->keylen;
87     c->algo = dek->algo;
88     make_session_key( c );
89     /*log_hexdump( "thekey", c->key, c->keylen );*/
90
91     buf[0] = c->algo;
92     memcpy( buf + 1, c->key, c->keylen );
93     
94     hd = cipher_open( dek->algo, CIPHER_MODE_CFB, 1 );
95     cipher_setkey( hd, dek->key, dek->keylen );
96     cipher_setiv( hd, NULL, 0 );
97     cipher_encrypt( hd, buf, buf, c->keylen + 1 );
98     cipher_close( hd );
99
100     memcpy( enckey, buf, c->keylen + 1 );
101     wipememory( buf, sizeof buf ); /* burn key */
102     *ret_dek = c;
103 }
104
105 /* We try very hard to use a MDC */
106 static int
107 use_mdc(PK_LIST pk_list,int algo)
108 {
109   /* --force-mdc overrides --disable-mdc */
110   if(opt.force_mdc)
111     return 1;
112
113   if(opt.disable_mdc)
114     return 0;
115
116   /* Do the keys really support MDC? */
117
118   if(select_mdc_from_pklist(pk_list))
119     return 1;
120   
121   /* The keys don't support MDC, so now we do a bit of a hack - if any
122      of the AESes or TWOFISH are in the prefs, we assume that the user
123      can handle a MDC.  This is valid for PGP 7, which can handle MDCs
124      though it will not generate them.  2440bis allows this, by the
125      way. */
126
127   if(select_algo_from_prefs(pk_list,PREFTYPE_SYM,
128                             CIPHER_ALGO_AES,NULL)==CIPHER_ALGO_AES)
129     return 1;
130
131   if(select_algo_from_prefs(pk_list,PREFTYPE_SYM,
132                             CIPHER_ALGO_AES192,NULL)==CIPHER_ALGO_AES192)
133     return 1;
134
135   if(select_algo_from_prefs(pk_list,PREFTYPE_SYM,
136                             CIPHER_ALGO_AES256,NULL)==CIPHER_ALGO_AES256)
137     return 1;
138
139   if(select_algo_from_prefs(pk_list,PREFTYPE_SYM,
140                             CIPHER_ALGO_TWOFISH,NULL)==CIPHER_ALGO_TWOFISH)
141     return 1;
142
143   /* Last try.  Use MDC for the modern ciphers. */
144
145   if(cipher_get_blocksize(algo)!=8)
146     return 1;
147
148   return 0; /* No MDC */
149 }
150
151 static int
152 encode_simple( const char *filename, int mode, int compat )
153 {
154     IOBUF inp, out;
155     PACKET pkt;
156     DEK *dek = NULL;
157     PKT_plaintext *pt = NULL;
158     STRING2KEY *s2k = NULL;
159     byte enckey[33];
160     int rc = 0;
161     int seskeylen = 0;
162     u32 filesize;
163     cipher_filter_context_t cfx;
164     armor_filter_context_t afx;
165     compress_filter_context_t zfx;
166     text_filter_context_t tfx;
167     int do_compress = opt.compress && !opt.rfc1991;
168
169     memset( &cfx, 0, sizeof cfx);
170     memset( &afx, 0, sizeof afx);
171     memset( &zfx, 0, sizeof zfx);
172     memset( &tfx, 0, sizeof tfx);
173     init_packet(&pkt);
174     
175     /* prepare iobufs */
176     if( !(inp = iobuf_open(filename)) ) {
177         log_error(_("%s: can't open: %s\n"), filename? filename: "[stdin]",
178                                         strerror(errno) );
179         return G10ERR_OPEN_FILE;
180     }
181
182     if( opt.textmode )
183         iobuf_push_filter( inp, text_filter, &tfx );
184
185     /* Due the the fact that we use don't use an IV to encrypt the
186        session key we can't use the new mode with RFC1991 because
187        it has no S2K salt. RFC1991 always uses simple S2K. */
188     if ( opt.rfc1991 && !compat )
189         compat = 1;
190     
191     cfx.dek = NULL;
192     if( mode ) {
193         s2k = m_alloc_clear( sizeof *s2k );
194         s2k->mode = opt.rfc1991? 0:opt.s2k_mode;
195         s2k->hash_algo = opt.s2k_digest_algo;
196         cfx.dek = passphrase_to_dek( NULL, 0,
197                   opt.def_cipher_algo ? opt.def_cipher_algo
198                                       : opt.s2k_cipher_algo , s2k, 2, NULL );
199         if( !cfx.dek || !cfx.dek->keylen ) {
200             rc = G10ERR_PASSPHRASE;
201             m_free(cfx.dek);
202             m_free(s2k);
203             iobuf_close(inp);
204             log_error(_("error creating passphrase: %s\n"), g10_errstr(rc) );
205             return rc;
206         }
207         if (!compat && s2k->mode != 1 && s2k->mode != 3) {
208             compat = 1;
209             log_info (_("can't use a symmetric ESK packet "
210                         "due to the S2K mode\n"));
211         }
212
213         if ( !compat ) {            
214             seskeylen = cipher_get_keylen( opt.def_cipher_algo ?
215                                            opt.def_cipher_algo:
216                                            opt.s2k_cipher_algo ) / 8;
217             encode_sesskey( cfx.dek, &dek, enckey );
218             m_free( cfx.dek ); cfx.dek = dek;
219         }
220
221         cfx.dek->use_mdc=use_mdc(NULL,cfx.dek->algo);
222     }
223
224     if (opt.compress == -1 && cfx.dek && cfx.dek->use_mdc &&
225         is_file_compressed(filename, &rc))
226       {
227         if (opt.verbose)
228           log_info(_("`%s' already compressed\n"), filename);
229         do_compress = 0;        
230       }
231
232     if( rc || (rc = open_outfile( filename, opt.armor? 1:0, &out )) ) {
233         iobuf_cancel(inp);
234         m_free(cfx.dek);
235         m_free(s2k);
236         return rc;
237     }
238
239     if( opt.armor )
240         iobuf_push_filter( out, armor_filter, &afx );
241   #ifdef ENABLE_COMMENT_PACKETS
242     else {
243         write_comment( out, "#created by GNUPG v" VERSION " ("
244                                             PRINTABLE_OS_NAME ")");
245         if( opt.comment_string )
246             write_comment( out, opt.comment_string );
247     }
248   #endif
249     if( s2k && !opt.rfc1991 ) {
250         PKT_symkey_enc *enc = m_alloc_clear( sizeof *enc + seskeylen + 1 );
251         enc->version = 4;
252         enc->cipher_algo = cfx.dek->algo;
253         enc->s2k = *s2k;
254         if ( !compat && seskeylen ) {
255             enc->seskeylen = seskeylen + 1; /* algo id */
256             memcpy( enc->seskey, enckey, seskeylen + 1 );
257         }
258         pkt.pkttype = PKT_SYMKEY_ENC;
259         pkt.pkt.symkey_enc = enc;
260         if( (rc = build_packet( out, &pkt )) )
261             log_error("build symkey packet failed: %s\n", g10_errstr(rc) );
262         m_free(enc);
263     }
264
265     if (!opt.no_literal) {
266         /* setup the inner packet */
267         if( filename || opt.set_filename ) {
268             char *s = make_basename( opt.set_filename ? opt.set_filename
269                                                       : filename,
270                                      iobuf_get_real_fname( inp ) );
271             pt = m_alloc( sizeof *pt + strlen(s) - 1 );
272             pt->namelen = strlen(s);
273             memcpy(pt->name, s, pt->namelen );
274             m_free(s);
275         }
276         else { /* no filename */
277             pt = m_alloc( sizeof *pt - 1 );
278             pt->namelen = 0;
279         }
280     }
281
282     /* Note that PGP 5 has problems decrypting symmetrically encrypted
283        data if the file length is in the inner packet. It works when
284        only partial length headers are use.  In the past, we always
285        used partial body length here, but since PGP 2, PGP 6, and PGP
286        7 need the file length, and nobody should be using PGP 5
287        nowadays anyway, this is now set to the file length.  Note also
288        that this only applies to the RFC-1991 style symmetric
289        messages, and not the RFC-2440 style.  PGP 6 and 7 work with
290        either partial length or fixed length with the new style
291        messages. */
292
293     if( filename && !opt.textmode ) {
294         off_t tmpsize;
295
296         if ( !(tmpsize = iobuf_get_filelength(inp)) )
297           log_info(_("%s: WARNING: empty file\n"), filename );
298         /* We can't encode the length of very large files because
299            OpenPGP uses only 32 bit for file sizes.  So if the the
300            size of a file is larger than 2^32 minus some bytes for
301            packet headers, we switch to partial length encoding. */
302         if ( tmpsize < (IOBUF_FILELENGTH_LIMIT - 65536) )
303           filesize = tmpsize;
304         else
305           filesize = 0;
306     }
307     else
308         filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */
309
310     if (!opt.no_literal) {
311         pt->timestamp = make_timestamp();
312         pt->mode = opt.textmode? 't' : 'b';
313         pt->len = filesize;
314         pt->new_ctb = !pt->len && !opt.rfc1991;
315         pt->buf = inp;
316         pkt.pkttype = PKT_PLAINTEXT;
317         pkt.pkt.plaintext = pt;
318         cfx.datalen = filesize && !do_compress ? calc_packet_length( &pkt ) : 0;
319     }
320     else
321       {
322         cfx.datalen = filesize && !do_compress ? filesize : 0;
323         pkt.pkttype = 0;
324         pkt.pkt.generic = NULL;
325       }
326
327     /* register the cipher filter */
328     if( mode )
329         iobuf_push_filter( out, cipher_filter, &cfx );
330     /* register the compress filter */
331     if( do_compress )
332       {
333         if (cfx.dek && cfx.dek->use_mdc)
334           zfx.new_ctb = 1;
335         zfx.algo=opt.def_compress_algo;
336         if(zfx.algo==-1)
337           zfx.algo=DEFAULT_COMPRESS_ALGO;
338         iobuf_push_filter( out, compress_filter, &zfx );
339       }
340
341     /* do the work */
342     if (!opt.no_literal) {
343         if( (rc = build_packet( out, &pkt )) )
344             log_error("build_packet failed: %s\n", g10_errstr(rc) );
345     }
346     else {
347         /* user requested not to create a literal packet,
348          * so we copy the plain data */
349         byte copy_buffer[4096];
350         int  bytes_copied;
351         while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1)
352             if (iobuf_write(out, copy_buffer, bytes_copied) == -1) {
353                 rc = G10ERR_WRITE_FILE;
354                 log_error("copying input to output failed: %s\n", g10_errstr(rc) );
355                 break;
356             }
357         wipememory(copy_buffer, 4096); /* burn buffer */
358     }
359
360     /* finish the stuff */
361     iobuf_close(inp);
362     if (rc)
363         iobuf_cancel(out);
364     else {
365         iobuf_close(out); /* fixme: check returncode */
366         if (mode)
367             write_status( STATUS_END_ENCRYPTION );
368     }
369     if (pt)
370         pt->buf = NULL;
371     free_packet(&pkt);
372     m_free(cfx.dek);
373     m_free(s2k);
374     return rc;
375 }
376
377 /****************
378  * Encrypt the file with the given userids (or ask if none
379  * is supplied).
380  */
381 int
382 encode_crypt( const char *filename, STRLIST remusr )
383 {
384     IOBUF inp = NULL, out = NULL;
385     PACKET pkt;
386     PKT_plaintext *pt = NULL;
387     int rc = 0, rc2 = 0;
388     u32 filesize;
389     cipher_filter_context_t cfx;
390     armor_filter_context_t afx;
391     compress_filter_context_t zfx;
392     text_filter_context_t tfx;
393     PK_LIST pk_list,work_list;
394     int do_compress = opt.compress && !opt.rfc1991;
395
396
397     memset( &cfx, 0, sizeof cfx);
398     memset( &afx, 0, sizeof afx);
399     memset( &zfx, 0, sizeof zfx);
400     memset( &tfx, 0, sizeof tfx);
401     init_packet(&pkt);
402
403     if( (rc=build_pk_list( remusr, &pk_list, PUBKEY_USAGE_ENC)) )
404         return rc;
405
406     if(opt.pgp2) {
407       for(work_list=pk_list; work_list; work_list=work_list->next)
408         if(!(is_RSA(work_list->pk->pubkey_algo) &&
409              nbits_from_pk(work_list->pk)<=2048))
410           {
411             log_info(_("you can only encrypt to RSA keys of 2048 bits or "
412                        "less in --pgp2 mode\n"));
413             log_info(_("this message may not be usable by %s\n"),"PGP 2.x");
414             opt.pgp2=0;
415             break;
416           }
417     }
418
419     /* prepare iobufs */
420     if( !(inp = iobuf_open(filename)) ) {
421         log_error(_("can't open %s: %s\n"), filename? filename: "[stdin]",
422                                         strerror(errno) );
423         rc = G10ERR_OPEN_FILE;
424         goto leave;
425     }
426     else if( opt.verbose )
427         log_info(_("reading from `%s'\n"), filename? filename: "[stdin]");
428
429     if( opt.textmode )
430         iobuf_push_filter( inp, text_filter, &tfx );
431
432     if( (rc = open_outfile( filename, opt.armor? 1:0, &out )) )
433         goto leave;
434
435
436     if( opt.armor )
437         iobuf_push_filter( out, armor_filter, &afx );
438   #ifdef ENABLE_COMMENT_PACKETS
439     else {
440         write_comment( out, "#created by GNUPG v" VERSION " ("
441                                             PRINTABLE_OS_NAME ")");
442         if( opt.comment_string )
443             write_comment( out, opt.comment_string );
444     }
445   #endif
446     /* create a session key */
447     cfx.dek = m_alloc_secure_clear (sizeof *cfx.dek);
448     if( !opt.def_cipher_algo ) { /* try to get it from the prefs */
449         cfx.dek->algo = select_algo_from_prefs(pk_list,PREFTYPE_SYM,-1,NULL);
450         /* The only way select_algo_from_prefs can fail here is when
451            mixing v3 and v4 keys, as v4 keys have an implicit
452            preference entry for 3DES, and the pk_list cannot be empty.
453            In this case, use 3DES anyway as it's the safest choice -
454            perhaps the v3 key is being used in an OpenPGP
455            implementation and we know that the implementation behind
456            any v4 key can handle 3DES. */
457         if( cfx.dek->algo == -1 ) {
458             cfx.dek->algo = CIPHER_ALGO_3DES;
459
460             if( opt.pgp2 ) {
461               log_info(_("unable to use the IDEA cipher for all of the keys "
462                          "you are encrypting to.\n"));
463               log_info(_("this message may not be usable by %s\n"),"PGP 2.x");
464               opt.pgp2=0;
465             }
466         }
467     }
468     else {
469       if(!opt.expert &&
470          select_algo_from_prefs(pk_list,PREFTYPE_SYM,
471                                 opt.def_cipher_algo,NULL)!=opt.def_cipher_algo)
472         log_info(_("forcing symmetric cipher %s (%d) "
473                    "violates recipient preferences\n"),
474                  cipher_algo_to_string(opt.def_cipher_algo),
475                  opt.def_cipher_algo);
476
477       cfx.dek->algo = opt.def_cipher_algo;
478     }
479
480     cfx.dek->use_mdc=use_mdc(pk_list,cfx.dek->algo);
481
482     /* Only do the is-file-already-compressed check if we are using a
483        MDC.  This forces compressed files to be re-compressed if we do
484        not have a MDC to give some protection against chosen
485        ciphertext attacks. */
486
487     if (opt.compress == -1 && cfx.dek->use_mdc &&
488         is_file_compressed(filename, &rc2) )
489       {
490         if (opt.verbose)
491           log_info(_("`%s' already compressed\n"), filename);
492         do_compress = 0;        
493       }
494     if (rc2)
495       {
496         rc = rc2;
497         goto leave;
498       }
499
500     make_session_key( cfx.dek );
501     if( DBG_CIPHER )
502         log_hexdump("DEK is: ", cfx.dek->key, cfx.dek->keylen );
503
504     rc = write_pubkey_enc_from_list( pk_list, cfx.dek, out );
505     if( rc  )
506         goto leave;
507
508     if (!opt.no_literal) {
509         /* setup the inner packet */
510         if( filename || opt.set_filename ) {
511             char *s = make_basename( opt.set_filename ? opt.set_filename
512                                                       : filename,
513                                      iobuf_get_real_fname( inp ) );
514             pt = m_alloc( sizeof *pt + strlen(s) - 1 );
515             pt->namelen = strlen(s);
516             memcpy(pt->name, s, pt->namelen );
517             m_free(s);
518         }
519         else { /* no filename */
520             pt = m_alloc( sizeof *pt - 1 );
521             pt->namelen = 0;
522         }
523     }
524
525     if( filename && !opt.textmode ) {
526         off_t tmpsize;
527
528         if ( !(tmpsize = iobuf_get_filelength(inp)) )
529           log_info(_("%s: WARNING: empty file\n"), filename );
530         /* We can't encode the length of very large files because
531            OpenPGP uses only 32 bit for file sizes.  So if the the
532            size of a file is larger than 2^32 minus some bytes for
533            packet headers, we switch to partial length encoding. */
534         if ( tmpsize < (IOBUF_FILELENGTH_LIMIT - 65536) )
535           filesize = tmpsize;
536         else
537           filesize = 0;
538     }
539     else
540         filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */
541
542     if (!opt.no_literal) {
543         pt->timestamp = make_timestamp();
544         pt->mode = opt.textmode ? 't' : 'b';
545         pt->len = filesize;
546         pt->new_ctb = !pt->len && !opt.rfc1991;
547         pt->buf = inp;
548         pkt.pkttype = PKT_PLAINTEXT;
549         pkt.pkt.plaintext = pt;
550         cfx.datalen = filesize && !do_compress? calc_packet_length( &pkt ) : 0;
551     }
552     else
553         cfx.datalen = filesize && !do_compress ? filesize : 0;
554
555     /* register the cipher filter */
556     iobuf_push_filter( out, cipher_filter, &cfx );
557
558     /* register the compress filter */
559     if( do_compress ) {
560         int compr_algo = opt.def_compress_algo;
561
562         if(compr_algo==-1)
563           {
564             if((compr_algo=
565                 select_algo_from_prefs(pk_list,PREFTYPE_ZIP,-1,NULL))==-1)
566               compr_algo=DEFAULT_COMPRESS_ALGO;
567           }
568         else if(!opt.expert &&
569                 select_algo_from_prefs(pk_list,PREFTYPE_ZIP,
570                                        compr_algo,NULL)!=compr_algo)
571           log_info(_("forcing compression algorithm %s (%d) "
572                      "violates recipient preferences\n"),
573                    compress_algo_to_string(compr_algo),compr_algo);
574
575         /* algo 0 means no compression */
576         if( compr_algo )
577           {
578             if (cfx.dek && cfx.dek->use_mdc)
579               zfx.new_ctb = 1;
580             zfx.algo = compr_algo;
581             iobuf_push_filter( out, compress_filter, &zfx );
582           }
583     }
584
585     /* do the work */
586     if (!opt.no_literal) {
587         if( (rc = build_packet( out, &pkt )) )
588             log_error("build_packet failed: %s\n", g10_errstr(rc) );
589     }
590     else {
591         /* user requested not to create a literal packet, so we copy
592            the plain data */
593         byte copy_buffer[4096];
594         int  bytes_copied;
595         while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1)
596             if (iobuf_write(out, copy_buffer, bytes_copied) == -1) {
597                 rc = G10ERR_WRITE_FILE;
598                 log_error("copying input to output failed: %s\n",
599                           g10_errstr(rc) );
600                 break;
601             }
602         wipememory(copy_buffer, 4096); /* burn buffer */
603     }
604
605     /* finish the stuff */
606   leave:
607     iobuf_close(inp);
608     if( rc )
609         iobuf_cancel(out);
610     else {
611         iobuf_close(out); /* fixme: check returncode */
612         write_status( STATUS_END_ENCRYPTION );
613     }
614     if( pt )
615         pt->buf = NULL;
616     free_packet(&pkt);
617     m_free(cfx.dek);
618     release_pk_list( pk_list );
619     return rc;
620 }
621
622
623
624
625 /****************
626  * Filter to do a complete public key encryption.
627  */
628 int
629 encrypt_filter( void *opaque, int control,
630                IOBUF a, byte *buf, size_t *ret_len)
631 {
632     size_t size = *ret_len;
633     encrypt_filter_context_t *efx = opaque;
634     int rc=0;
635
636     if( control == IOBUFCTRL_UNDERFLOW ) { /* decrypt */
637         BUG(); /* not used */
638     }
639     else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */
640         if( !efx->header_okay ) {
641             efx->cfx.dek = m_alloc_secure_clear( sizeof *efx->cfx.dek );
642
643             if( !opt.def_cipher_algo  ) { /* try to get it from the prefs */
644                 efx->cfx.dek->algo =
645                   select_algo_from_prefs(efx->pk_list,PREFTYPE_SYM,-1,NULL);
646                 if( efx->cfx.dek->algo == -1 ) {
647                     /* because 3DES is implicitly in the prefs, this can only
648                      * happen if we do not have any public keys in the list */
649                     efx->cfx.dek->algo = DEFAULT_CIPHER_ALGO;
650                 }
651             }
652             else {
653               if(!opt.expert &&
654                  select_algo_from_prefs(efx->pk_list,PREFTYPE_SYM,
655                                         opt.def_cipher_algo,
656                                         NULL)!=opt.def_cipher_algo)
657                 log_info(_("forcing symmetric cipher %s (%d) "
658                            "violates recipient preferences\n"),
659                          cipher_algo_to_string(opt.def_cipher_algo),
660                          opt.def_cipher_algo);
661
662               efx->cfx.dek->algo = opt.def_cipher_algo;
663             }
664
665             efx->cfx.dek->use_mdc = use_mdc(efx->pk_list,efx->cfx.dek->algo);
666
667             make_session_key( efx->cfx.dek );
668             if( DBG_CIPHER )
669                 log_hexdump("DEK is: ",
670                              efx->cfx.dek->key, efx->cfx.dek->keylen );
671
672             rc = write_pubkey_enc_from_list( efx->pk_list, efx->cfx.dek, a );
673             if( rc )
674                 return rc;
675
676             iobuf_push_filter( a, cipher_filter, &efx->cfx );
677
678             efx->header_okay = 1;
679         }
680         rc = iobuf_write( a, buf, size );
681
682     }
683     else if( control == IOBUFCTRL_FREE ) {
684     }
685     else if( control == IOBUFCTRL_DESC ) {
686         *(char**)buf = "encrypt_filter";
687     }
688     return rc;
689 }
690
691
692 /****************
693  * Write pubkey-enc packets from the list of PKs to OUT.
694  */
695 static int
696 write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out )
697 {
698     PACKET pkt;
699     PKT_public_key *pk;
700     PKT_pubkey_enc  *enc;
701     int rc;
702
703     for( ; pk_list; pk_list = pk_list->next ) {
704         MPI frame;
705
706         pk = pk_list->pk;
707
708         print_pubkey_algo_note( pk->pubkey_algo );
709         enc = m_alloc_clear( sizeof *enc );
710         enc->pubkey_algo = pk->pubkey_algo;
711         keyid_from_pk( pk, enc->keyid );
712         enc->throw_keyid = (opt.throw_keyid || (pk_list->flags&1));
713
714         if(opt.throw_keyid && (opt.pgp2 || opt.pgp6 || opt.pgp7))
715           {
716             log_info(_("you may not use %s while in %s mode\n"),
717                      "--throw-keyid",
718                      opt.pgp2?"--pgp2":opt.pgp6?"--pgp6":"--pgp7");
719
720             log_info(_("this message may not be usable by %s\n"),
721                      opt.pgp2?"PGP 2.x":opt.pgp6?"PGP 6.x":"PGP 7.x");
722
723             opt.pgp2=opt.pgp6=opt.pgp7=0;
724           }
725
726         /* Okay, what's going on: We have the session key somewhere in
727          * the structure DEK and want to encode this session key in
728          * an integer value of n bits.  pubkey_nbits gives us the
729          * number of bits we have to use.  We then encode the session
730          * key in some way and we get it back in the big intger value
731          * FRAME.  Then we use FRAME, the public key PK->PKEY and the
732          * algorithm number PK->PUBKEY_ALGO and pass it to pubkey_encrypt
733          * which returns the encrypted value in the array ENC->DATA.
734          * This array has a size which depends on the used algorithm
735          * (e.g. 2 for ElGamal).  We don't need frame anymore because we
736          * have everything now in enc->data which is the passed to
737          * build_packet()
738          */
739         frame = encode_session_key( dek, pubkey_nbits( pk->pubkey_algo,
740                                                           pk->pkey ) );
741         rc = pubkey_encrypt( pk->pubkey_algo, enc->data, frame, pk->pkey );
742         mpi_free( frame );
743         if( rc )
744             log_error("pubkey_encrypt failed: %s\n", g10_errstr(rc) );
745         else {
746             if( opt.verbose ) {
747                 char *ustr = get_user_id_string_printable (enc->keyid);
748                 log_info(_("%s/%s encrypted for: \"%s\"\n"),
749                     pubkey_algo_to_string(enc->pubkey_algo),
750                     cipher_algo_to_string(dek->algo), ustr );
751                 m_free(ustr);
752             }
753             /* and write it */
754             init_packet(&pkt);
755             pkt.pkttype = PKT_PUBKEY_ENC;
756             pkt.pkt.pubkey_enc = enc;
757             rc = build_packet( out, &pkt );
758             if( rc )
759                log_error("build_packet(pubkey_enc) failed: %s\n", g10_errstr(rc));
760         }
761         free_pubkey_enc(enc);
762         if( rc )
763             return rc;
764     }
765     return 0;
766 }
767
768 void
769 encode_crypt_files(int nfiles, char **files, STRLIST remusr)
770 {
771   int rc = 0;
772
773   if (opt.outfile)
774     {
775       log_error(_("--output doesn't work for this command\n"));
776       return;        
777     }
778     
779   if (!nfiles)
780     {
781       char line[2048];
782       unsigned int lno = 0;
783       while ( fgets(line, DIM(line), stdin) )
784         {
785           lno++;
786           if (!*line || line[strlen(line)-1] != '\n')
787             {
788               log_error("input line %u too long or missing LF\n", lno);
789               return;
790             }
791           line[strlen(line)-1] = '\0';
792           print_file_status(STATUS_FILE_START, line, 2);
793           if ( (rc = encode_crypt(line, remusr)) )
794             log_error("%s: encryption failed: %s\n",
795                       print_fname_stdin(line), g10_errstr(rc) );
796           write_status( STATUS_FILE_DONE );
797         }
798     }
799   else
800     {
801       while (nfiles--)
802         {
803           print_file_status(STATUS_FILE_START, *files, 2);
804           if ( (rc = encode_crypt(*files, remusr)) )
805             log_error("%s: encryption failed: %s\n",
806                       print_fname_stdin(*files), g10_errstr(rc) );
807           write_status( STATUS_FILE_DONE );
808           files++;
809         }
810     }
811 }