add salted and iterated mode
[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 "memory.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 /****************
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     return encode_simple( filename, 1 );
54 }
55
56 /****************
57  * Encode FILENAME as a literal data packet only. Take input from
58  * stdin if FILENAME is NULL.
59  */
60 int
61 encode_store( const char *filename )
62 {
63     return encode_simple( filename, 0 );
64 }
65
66
67 static int
68 encode_simple( const char *filename, int mode )
69 {
70     IOBUF inp, out;
71     PACKET pkt;
72     PKT_plaintext *pt;
73     STRING2KEY *s2k = NULL;
74     int rc = 0;
75     u32 filesize;
76     cipher_filter_context_t cfx;
77     armor_filter_context_t afx;
78     compress_filter_context_t zfx;
79
80     memset( &cfx, 0, sizeof cfx);
81     memset( &afx, 0, sizeof afx);
82     memset( &zfx, 0, sizeof zfx);
83
84     /* prepare iobufs */
85     if( !(inp = iobuf_open(filename)) ) {
86         log_error(_("%s: can't open: %s\n"), filename? filename: "[stdin]",
87                                         strerror(errno) );
88         return G10ERR_OPEN_FILE;
89     }
90
91     cfx.dek = NULL;
92     if( mode ) {
93         s2k = m_alloc_clear( sizeof *s2k );
94         s2k->mode = opt.rfc1991? 0:1;
95         s2k->hash_algo = opt.def_digest_algo ? opt.def_digest_algo
96                                              : DEFAULT_DIGEST_ALGO;
97         cfx.dek = passphrase_to_dek( NULL,
98                        opt.def_cipher_algo ? opt.def_cipher_algo
99                                            : DEFAULT_CIPHER_ALGO , s2k, 2 );
100         if( !cfx.dek || !cfx.dek->keylen ) {
101             rc = G10ERR_PASSPHRASE;
102             m_free(cfx.dek);
103             m_free(s2k);
104             iobuf_close(inp);
105             log_error(_("error creating passphrase: %s\n"), g10_errstr(rc) );
106             return rc;
107         }
108     }
109
110     if( !(out = open_outfile( filename, opt.armor? 1:0 )) ) {
111         iobuf_close(inp);
112         m_free(cfx.dek);
113         m_free(s2k);
114         return G10ERR_CREATE_FILE;  /* or user said: do not overwrite */
115     }
116
117     if( opt.armor )
118         iobuf_push_filter( out, armor_filter, &afx );
119     else
120         write_comment( out, "#created by GNUPG v" VERSION " ("
121                                             PRINTABLE_OS_NAME ")");
122
123     if( s2k && !opt.rfc1991 ) {
124         PKT_symkey_enc *enc = m_alloc_clear( sizeof *enc );
125         enc->version = 4;
126         enc->cipher_algo = cfx.dek->algo;
127         enc->s2k = *s2k;
128         pkt.pkttype = PKT_SYMKEY_ENC;
129         pkt.pkt.symkey_enc = enc;
130         if( (rc = build_packet( out, &pkt )) )
131             log_error("build symkey packet failed: %s\n", g10_errstr(rc) );
132         m_free(enc);
133     }
134
135     /* setup the inner packet */
136     if( filename ) {
137         pt = m_alloc( sizeof *pt + strlen(filename) - 1 );
138         pt->namelen = strlen(filename);
139         memcpy(pt->name, filename, pt->namelen );
140         if( !(filesize = iobuf_get_filelength(inp)) )
141             log_info(_("%s: warning: empty file\n"), filename );
142     }
143     else { /* no filename */
144         pt = m_alloc( sizeof *pt - 1 );
145         pt->namelen = 0;
146         filesize = 0; /* stdin */
147     }
148     pt->timestamp = make_timestamp();
149     pt->mode = 'b';
150     pt->len = filesize;
151     pt->buf = inp;
152     pkt.pkttype = PKT_PLAINTEXT;
153     pkt.pkt.plaintext = pt;
154     cfx.datalen = filesize && !opt.compress ? calc_packet_length( &pkt ) : 0;
155
156     /* register the cipher filter */
157     if( mode )
158         iobuf_push_filter( out, cipher_filter, &cfx );
159     /* register the compress filter */
160     if( opt.compress )
161         iobuf_push_filter( out, compress_filter, &zfx );
162
163     /* do the work */
164     if( (rc = build_packet( out, &pkt )) )
165         log_error("build_packet failed: %s\n", g10_errstr(rc) );
166
167     /* finish the stuff */
168     iobuf_close(inp);
169     iobuf_close(out); /* fixme: check returncode */
170     pt->buf = NULL;
171     free_packet(&pkt);
172     m_free(cfx.dek);
173     m_free(s2k);
174     return rc;
175 }
176
177 /****************
178  * Encrypt the file with the given userids (or ask if none
179  * is supplied).
180  */
181 int
182 encode_crypt( const char *filename, STRLIST remusr )
183 {
184     IOBUF inp = NULL, out = NULL;
185     PACKET pkt;
186     PKT_plaintext *pt = NULL;
187     int rc = 0;
188     u32 filesize;
189     cipher_filter_context_t cfx;
190     armor_filter_context_t afx;
191     compress_filter_context_t zfx;
192     PK_LIST pk_list;
193
194     memset( &cfx, 0, sizeof cfx);
195     memset( &afx, 0, sizeof afx);
196     memset( &zfx, 0, sizeof zfx);
197
198     if( (rc=build_pk_list( remusr, &pk_list, PUBKEY_USAGE_ENC)) )
199         return rc;
200
201     /* prepare iobufs */
202     if( !(inp = iobuf_open(filename)) ) {
203         log_error(_("can't open %s: %s\n"), filename? filename: "[stdin]",
204                                         strerror(errno) );
205         rc = G10ERR_OPEN_FILE;
206         goto leave;
207     }
208     else if( opt.verbose )
209         log_info(_("reading from '%s'\n"), filename? filename: "[stdin]");
210
211     if( !(out = open_outfile( filename, opt.armor? 1:0 )) ) {
212         rc = G10ERR_CREATE_FILE;  /* or user said: do not overwrite */
213         goto leave;
214     }
215
216     if( opt.armor )
217         iobuf_push_filter( out, armor_filter, &afx );
218     else
219         write_comment( out, "#created by GNUPG v" VERSION " ("
220                                             PRINTABLE_OS_NAME ")");
221
222     /* create a session key */
223     cfx.dek = m_alloc_secure( sizeof *cfx.dek );
224     if( !opt.def_cipher_algo ) { /* try to get it from the prefs */
225         cfx.dek->algo = select_algo_from_prefs( pk_list, PREFTYPE_SYM );
226         if( cfx.dek->algo == -1 )
227             cfx.dek->algo = DEFAULT_CIPHER_ALGO;
228     }
229     else
230         cfx.dek->algo = opt.def_cipher_algo;
231     make_session_key( cfx.dek );
232     if( DBG_CIPHER )
233         log_hexdump("DEK is: ", cfx.dek->key, cfx.dek->keylen );
234
235     rc = write_pubkey_enc_from_list( pk_list, cfx.dek, out );
236     if( rc  )
237         goto leave;
238
239     /* setup the inner packet */
240     if( filename ) {
241         pt = m_alloc( sizeof *pt + strlen(filename) - 1 );
242         pt->namelen = strlen(filename);
243         memcpy(pt->name, filename, pt->namelen );
244         if( !(filesize = iobuf_get_filelength(inp)) )
245             log_info(_("%s: warning: empty file\n"), filename );
246     }
247     else { /* no filename */
248         pt = m_alloc( sizeof *pt - 1 );
249         pt->namelen = 0;
250         filesize = 0; /* stdin */
251     }
252     pt->timestamp = make_timestamp();
253     pt->mode = 'b';
254     pt->len = filesize;
255     pt->new_ctb = !pt->len && !opt.rfc1991;
256     pt->buf = inp;
257     init_packet(&pkt);
258     pkt.pkttype = PKT_PLAINTEXT;
259     pkt.pkt.plaintext = pt;
260     cfx.datalen = filesize && !opt.compress? calc_packet_length( &pkt ) : 0;
261
262     /* register the cipher filter */
263     iobuf_push_filter( out, cipher_filter, &cfx );
264     /* register the compress filter */
265     if( opt.compress ) {
266         int compr_algo = select_algo_from_prefs( pk_list, PREFTYPE_COMPR );
267         if( !compr_algo )
268             ; /* don't use compression */
269         else {
270             if( compr_algo == 1 )
271                 zfx.algo = 1; /* default is 2 */
272             iobuf_push_filter( out, compress_filter, &zfx );
273         }
274     }
275
276     /* do the work */
277     if( (rc = build_packet( out, &pkt )) )
278         log_error("build_packet failed: %s\n", g10_errstr(rc) );
279
280     /* finish the stuff */
281   leave:
282     iobuf_close(inp);
283     if( rc )
284         iobuf_cancel(out);
285     else
286         iobuf_close(out); /* fixme: check returncode */
287     if( pt )
288         pt->buf = NULL;
289     free_packet(&pkt);
290     m_free(cfx.dek);
291     release_pk_list( pk_list );
292     return rc;
293 }
294
295
296 /****************
297  * Filter to do a complete public key encryption.
298  */
299 int
300 encrypt_filter( void *opaque, int control,
301                IOBUF a, byte *buf, size_t *ret_len)
302 {
303     size_t size = *ret_len;
304     encrypt_filter_context_t *efx = opaque;
305     int rc=0;
306
307     if( control == IOBUFCTRL_UNDERFLOW ) { /* decrypt */
308         BUG(); /* not used */
309     }
310     else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */
311         if( !efx->header_okay ) {
312             efx->cfx.dek = m_alloc_secure( sizeof *efx->cfx.dek );
313
314             if( !opt.def_cipher_algo  ) { /* try to get it from the prefs */
315                 efx->cfx.dek->algo =
316                           select_algo_from_prefs( efx->pk_list, PREFTYPE_SYM );
317                 if( efx->cfx.dek->algo == -1 )
318                     efx->cfx.dek->algo = DEFAULT_CIPHER_ALGO;
319             }
320             else
321                 efx->cfx.dek->algo = opt.def_cipher_algo;
322             make_session_key( efx->cfx.dek );
323             if( DBG_CIPHER )
324                 log_hexdump("DEK is: ",
325                              efx->cfx.dek->key, efx->cfx.dek->keylen );
326
327             rc = write_pubkey_enc_from_list( efx->pk_list, efx->cfx.dek, a );
328             if( rc )
329                 return rc;
330
331             iobuf_push_filter( a, cipher_filter, &efx->cfx );
332
333             efx->header_okay = 1;
334         }
335         rc = iobuf_write( a, buf, size );
336
337     }
338     else if( control == IOBUFCTRL_FREE ) {
339     }
340     else if( control == IOBUFCTRL_DESC ) {
341         *(char**)buf = "encrypt_filter";
342     }
343     return rc;
344 }
345
346
347 /****************
348  * Write pubkey-enc packets from the list of PKs to OUT.
349  */
350 static int
351 write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out )
352 {
353     PACKET pkt;
354     PKT_public_key *pk;
355     PKT_pubkey_enc  *enc;
356     int rc;
357
358     for( ; pk_list; pk_list = pk_list->next ) {
359         MPI frame;
360
361         pk = pk_list->pk;
362         if( is_RSA(pk->pubkey_algo) )
363             do_not_use_RSA();
364         enc = m_alloc_clear( sizeof *enc );
365         enc->pubkey_algo = pk->pubkey_algo;
366         keyid_from_pk( pk, enc->keyid );
367         frame = encode_session_key( dek, pubkey_nbits( pk->pubkey_algo,
368                                                           pk->pkey ) );
369         rc = pubkey_encrypt( pk->pubkey_algo, enc->data, frame, pk->pkey );
370         mpi_free( frame );
371         if( rc )
372             log_error("pubkey_encrypt failed: %s\n", g10_errstr(rc) );
373         else {
374             if( opt.verbose ) {
375                 char *ustr = get_user_id_string( enc->keyid );
376                 log_info(_("%s encrypted for: %s\n"),
377                     pubkey_algo_to_string(enc->pubkey_algo), ustr );
378                 m_free(ustr);
379             }
380             /* and write it */
381             init_packet(&pkt);
382             pkt.pkttype = PKT_PUBKEY_ENC;
383             pkt.pkt.pubkey_enc = enc;
384             rc = build_packet( out, &pkt );
385             if( rc )
386                log_error("build_packet(pubkey_enc) failed: %s\n", g10_errstr(rc));
387         }
388         free_pubkey_enc(enc);
389         if( rc )
390             return rc;
391     }
392     return 0;
393 }
394