See ChangeLog: Tue Jul 25 17:44:15 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_cdr_mpi( list, 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_cdr_mpi( list, 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     }
224     else
225         filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */
226
227     if (!opt.no_literal) {
228         pt->timestamp = make_timestamp();
229         pt->mode = opt.textmode? 't' : 'b';
230         pt->len = filesize;
231         pt->new_ctb = !pt->len && !opt.rfc1991;
232         pt->buf = inp;
233         pkt.pkttype = PKT_PLAINTEXT;
234         pkt.pkt.plaintext = pt;
235         cfx.datalen = filesize && !do_compress ? calc_packet_length( &pkt ) : 0;
236     }
237     else
238         cfx.datalen = filesize && !do_compress ? filesize : 0;
239
240     /* register the cipher filter */
241     if( mode )
242         iobuf_push_filter( out, cipher_filter, &cfx );
243     /* register the compress filter */
244     if( do_compress )
245         iobuf_push_filter( out, compress_filter, &zfx );
246
247     /* do the work */
248     if (!opt.no_literal) {
249         if( (rc = build_packet( out, &pkt )) )
250             log_error("build_packet failed: %s\n", gpg_errstr(rc) );
251     }
252     else {
253         /* user requested not to create a literal packet,
254          * so we copy the plain data */
255         byte copy_buffer[4096];
256         int  bytes_copied;
257         while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1)
258             if (iobuf_write(out, copy_buffer, bytes_copied) == -1) {
259                 rc = GPGERR_WRITE_FILE;
260                 log_error("copying input to output failed: %s\n", gpg_errstr(rc) );
261                 break;
262             }
263         memset(copy_buffer, 0, 4096); /* burn buffer */
264     }
265
266     /* finish the stuff */
267     iobuf_close(inp);
268     if (rc)
269         iobuf_cancel(out);
270     else
271         iobuf_close(out); /* fixme: check returncode */
272     if (pt)
273         pt->buf = NULL;
274     free_packet(&pkt);
275     gcry_free(cfx.dek);
276     gcry_free(s2k);
277     return rc;
278 }
279
280 /****************
281  * Encrypt the file with the given userids (or ask if none
282  * is supplied).
283  */
284 int
285 encode_crypt( const char *filename, STRLIST remusr )
286 {
287     IOBUF inp = NULL, out = NULL;
288     PACKET pkt;
289     PKT_plaintext *pt = NULL;
290     int rc = 0;
291     u32 filesize;
292     cipher_filter_context_t cfx;
293     armor_filter_context_t afx;
294     compress_filter_context_t zfx;
295     text_filter_context_t tfx;
296     PK_LIST pk_list;
297     int do_compress = opt.compress && !opt.rfc1991;
298
299
300     memset( &cfx, 0, sizeof cfx);
301     memset( &afx, 0, sizeof afx);
302     memset( &zfx, 0, sizeof zfx);
303     memset( &tfx, 0, sizeof tfx);
304     init_packet(&pkt);
305
306     if( (rc=build_pk_list( remusr, &pk_list, GCRY_PK_USAGE_ENCR)) )
307         return rc;
308
309     /* prepare iobufs */
310     if( !(inp = iobuf_open(filename)) ) {
311         log_error(_("can't open %s: %s\n"), filename? filename: "[stdin]",
312                                         strerror(errno) );
313         rc = GPGERR_OPEN_FILE;
314         goto leave;
315     }
316     else if( opt.verbose )
317         log_info(_("reading from `%s'\n"), filename? filename: "[stdin]");
318
319     if( opt.textmode )
320         iobuf_push_filter( inp, text_filter, &tfx );
321
322     if( (rc = open_outfile( filename, opt.armor? 1:0, &out )) )
323         goto leave;
324
325
326     if( opt.armor )
327         iobuf_push_filter( out, armor_filter, &afx );
328   #ifdef ENABLE_COMMENT_PACKETS
329     else {
330         write_comment( out, "#created by GNUPG v" VERSION " ("
331                                             PRINTABLE_OS_NAME ")");
332         if( opt.comment_string )
333             write_comment( out, opt.comment_string );
334     }
335   #endif
336     /* create a session key */
337     cfx.dek = gcry_xmalloc_secure( sizeof *cfx.dek );
338     if( !opt.def_cipher_algo ) { /* try to get it from the prefs */
339         cfx.dek->algo = select_algo_from_prefs( pk_list, PREFTYPE_SYM );
340         if( cfx.dek->algo == -1 )
341             cfx.dek->algo = DEFAULT_CIPHER_ALGO;
342     }
343     else
344         cfx.dek->algo = opt.def_cipher_algo;
345     make_session_key( cfx.dek );
346     if( DBG_CIPHER )
347         log_hexdump("DEK is: ", cfx.dek->key, cfx.dek->keylen );
348
349     rc = write_pubkey_enc_from_list( pk_list, cfx.dek, out );
350     if( rc  )
351         goto leave;
352
353     if (!opt.no_literal) {
354         /* setup the inner packet */
355         if( filename || opt.set_filename ) {
356             char *s = make_basename( opt.set_filename ? opt.set_filename : filename );
357             pt = gcry_xmalloc( sizeof *pt + strlen(s) - 1 );
358             pt->namelen = strlen(s);
359             memcpy(pt->name, s, pt->namelen );
360             gcry_free(s);
361         }
362         else { /* no filename */
363             pt = gcry_xmalloc( sizeof *pt - 1 );
364             pt->namelen = 0;
365         }
366     }
367
368     if( filename && !opt.textmode ) {
369         if( !(filesize = iobuf_get_filelength(inp)) )
370             log_info(_("%s: WARNING: empty file\n"), filename );
371     }
372     else
373         filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */
374
375     if (!opt.no_literal) {
376         pt->timestamp = make_timestamp();
377         pt->mode = opt.textmode ? 't' : 'b';
378         pt->len = filesize;
379         pt->new_ctb = !pt->len && !opt.rfc1991;
380         pt->buf = inp;
381         pkt.pkttype = PKT_PLAINTEXT;
382         pkt.pkt.plaintext = pt;
383         cfx.datalen = filesize && !do_compress? calc_packet_length( &pkt ) : 0;
384     }
385     else
386         cfx.datalen = filesize && !do_compress ? filesize : 0;
387
388     /* register the cipher filter */
389     iobuf_push_filter( out, cipher_filter, &cfx );
390
391     /* register the compress filter */
392     if( do_compress ) {
393         int compr_algo = select_algo_from_prefs( pk_list, PREFTYPE_COMPR );
394         if( !compr_algo )
395             ; /* don't use compression */
396         else {
397             if( compr_algo == 1 )
398                 zfx.algo = 1; /* default is 2 */
399             iobuf_push_filter( out, compress_filter, &zfx );
400         }
401     }
402
403     /* do the work */
404     if (!opt.no_literal) {
405         if( (rc = build_packet( out, &pkt )) )
406             log_error("build_packet failed: %s\n", gpg_errstr(rc) );
407     }
408     else {
409         /* user requested not to create a literal packet, so we copy the plain data */
410         byte copy_buffer[4096];
411         int  bytes_copied;
412         while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1)
413             if (iobuf_write(out, copy_buffer, bytes_copied) == -1) {
414                 rc = GPGERR_WRITE_FILE;
415                 log_error("copying input to output failed: %s\n", gpg_errstr(rc) );
416                 break;
417             }
418         memset(copy_buffer, 0, 4096); /* burn buffer */
419     }
420
421     /* finish the stuff */
422   leave:
423     iobuf_close(inp);
424     if( rc )
425         iobuf_cancel(out);
426     else
427         iobuf_close(out); /* fixme: check returncode */
428     if( pt )
429         pt->buf = NULL;
430     free_packet(&pkt);
431     gcry_free(cfx.dek);
432     release_pk_list( pk_list );
433     return rc;
434 }
435
436
437
438
439 /****************
440  * Filter to do a complete public key encryption.
441  */
442 int
443 encrypt_filter( void *opaque, int control,
444                IOBUF a, byte *buf, size_t *ret_len)
445 {
446     size_t size = *ret_len;
447     encrypt_filter_context_t *efx = opaque;
448     int rc=0;
449
450     if( control == IOBUFCTRL_UNDERFLOW ) { /* decrypt */
451         BUG(); /* not used */
452     }
453     else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */
454         if( !efx->header_okay ) {
455             efx->cfx.dek = gcry_xmalloc_secure( sizeof *efx->cfx.dek );
456
457             if( !opt.def_cipher_algo  ) { /* try to get it from the prefs */
458                 efx->cfx.dek->algo =
459                           select_algo_from_prefs( efx->pk_list, PREFTYPE_SYM );
460                 if( efx->cfx.dek->algo == -1 )
461                     efx->cfx.dek->algo = DEFAULT_CIPHER_ALGO;
462             }
463             else
464                 efx->cfx.dek->algo = opt.def_cipher_algo;
465             make_session_key( efx->cfx.dek );
466             if( DBG_CIPHER )
467                 log_hexdump("DEK is: ",
468                              efx->cfx.dek->key, efx->cfx.dek->keylen );
469
470             rc = write_pubkey_enc_from_list( efx->pk_list, efx->cfx.dek, a );
471             if( rc )
472                 return rc;
473
474             iobuf_push_filter( a, cipher_filter, &efx->cfx );
475
476             efx->header_okay = 1;
477         }
478         rc = iobuf_write( a, buf, size );
479
480     }
481     else if( control == IOBUFCTRL_FREE ) {
482     }
483     else if( control == IOBUFCTRL_DESC ) {
484         *(char**)buf = "encrypt_filter";
485     }
486     return rc;
487 }
488
489
490 /****************
491  * Write pubkey-enc packets from the list of PKs to OUT.
492  */
493 static int
494 write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out )
495 {
496     PACKET pkt;
497     PKT_public_key *pk;
498     PKT_pubkey_enc  *enc;
499     int rc;
500
501     for( ; pk_list; pk_list = pk_list->next ) {
502         MPI frame;
503
504         pk = pk_list->pk;
505
506         print_pubkey_algo_note( pk->pubkey_algo );
507         enc = gcry_xcalloc( 1, sizeof *enc );
508         enc->pubkey_algo = pk->pubkey_algo;
509         keyid_from_pk( pk, enc->keyid );
510         enc->throw_keyid = opt.throw_keyid;
511
512         /* Okay, what's going on: We have the session key somewhere in
513          * the structure DEK and want to encode this session key in
514          * an integer value of n bits.  pubkey_nbits gives us the
515          * number of bits we have to use.  We then encode the session
516          * key in some way and we get it back in the big intger value
517          * FRAME.  Then we use FRAME, the public key PK->PKEY and the
518          * algorithm number PK->PUBKEY_ALGO and pass it to pubkey_encrypt
519          * which returns the encrypted value in the array ENC->DATA.
520          * This array has a size which depends on the used algorithm
521          * (e.g. 2 for ElGamal).  We don't need frame anymore because we
522          * have everything now in enc->data which is the passed to
523          * build_packet()
524          */
525         frame = encode_session_key( dek, pubkey_nbits( pk->pubkey_algo,
526                                                           pk->pkey ) );
527         rc = pk_encrypt( pk->pubkey_algo, enc->data, frame, pk->pkey );
528         mpi_release( frame );
529         if( rc )
530             log_error("pubkey_encrypt failed: %s\n", gpg_errstr(rc) );
531         else {
532             if( opt.verbose ) {
533                 char *ustr = get_user_id_string_native( enc->keyid );
534                 log_info(_("%s/%s encrypted for: %s\n"),
535                     gcry_pk_algo_name(enc->pubkey_algo),
536                     gcry_cipher_algo_name(dek->algo), ustr );
537                 gcry_free(ustr);
538             }
539             /* and write it */
540             init_packet(&pkt);
541             pkt.pkttype = PKT_PUBKEY_ENC;
542             pkt.pkt.pubkey_enc = enc;
543             rc = build_packet( out, &pkt );
544             if( rc )
545                log_error("build_packet(pubkey_enc) failed: %s\n", gpg_errstr(rc));
546         }
547         free_pubkey_enc(enc);
548         if( rc )
549             return rc;
550     }
551     return 0;
552 }
553