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