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