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