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