Sylvester Version
[gnupg.git] / g10 / encode.c
1 /* encode.c - encode data
2  *      Copyright (c) 1997 by Werner Koch (dd9jn)
3  *
4  * This file is part of G10.
5  *
6  * G10 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  * G10 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
41
42
43 /****************
44  * Encode FILENAME only with the symmetric cipher. Take input from
45  * stdin if FILENAME is NULL.
46  */
47 int
48 encode_symmetric( const char *filename )
49 {
50     return encode_simple( filename, 1 );
51 }
52
53 /****************
54  * Encode FILENAME as literal data packet only. Take input from
55  * stdin if FILENAME is NULL.
56  */
57 int
58 encode_store( const char *filename )
59 {
60     return encode_simple( filename, 0 );
61 }
62
63
64 static int
65 encode_simple( const char *filename, int mode )
66 {
67     IOBUF inp, out;
68     PACKET pkt;
69     PKT_plaintext *pt;
70     int rc = 0;
71     u32 filesize;
72     cipher_filter_context_t cfx;
73     armor_filter_context_t afx;
74     compress_filter_context_t zfx;
75
76     memset( &cfx, 0, sizeof cfx);
77     memset( &afx, 0, sizeof afx);
78     memset( &zfx, 0, sizeof zfx);
79
80     /* prepare iobufs */
81     if( !(inp = iobuf_open(filename)) ) {
82         log_error("can't open %s: %s\n", filename? filename: "[stdin]",
83                                         strerror(errno) );
84         return G10ERR_OPEN_FILE;
85     }
86
87     cfx.dek = NULL;
88     if( mode ) {
89         cfx.dek = m_alloc_secure( sizeof *cfx.dek );
90         cfx.dek->algo = DEFAULT_CIPHER_ALGO;
91         if( (rc = make_dek_from_passphrase( cfx.dek , 2 )) ) {
92             m_free(cfx.dek);
93             iobuf_close(inp);
94             log_error("error creating passphrase: %s\n", g10_errstr(rc) );
95             return rc;
96         }
97     }
98
99     if( !(out = open_outfile( filename, opt.armor? 1:0 )) ) {
100         iobuf_close(inp);
101         m_free(cfx.dek);
102         return G10ERR_CREATE_FILE;  /* or user said: do not overwrite */
103     }
104
105     if( opt.armor )
106         iobuf_push_filter( out, armor_filter, &afx );
107
108     write_comment( out, "#Created by G10 pre-release " VERSION );
109
110     if( opt.compress )
111         iobuf_push_filter( out, compress_filter, &zfx );
112
113
114     /* setup the inner packet */
115     if( filename ) {
116         pt = m_alloc( sizeof *pt + strlen(filename) - 1 );
117         pt->namelen = strlen(filename);
118         memcpy(pt->name, filename, pt->namelen );
119         if( !(filesize = iobuf_get_filelength(inp)) )
120             log_info("warning: '%s' is an empty file\n", filename );
121     }
122     else { /* no filename */
123         pt = m_alloc( sizeof *pt - 1 );
124         pt->namelen = 0;
125         filesize = 0; /* stdin */
126     }
127     pt->timestamp = make_timestamp();
128     pt->mode = 'b';
129     pt->len = filesize;
130     pt->buf = inp;
131     pkt.pkttype = PKT_PLAINTEXT;
132     pkt.pkt.plaintext = pt;
133     cfx.datalen = filesize? calc_packet_length( &pkt ) : 0;
134
135     /* register the cipher filter */
136     if( mode )
137         iobuf_push_filter( out, cipher_filter, &cfx );
138
139     /* do the work */
140     if( (rc = build_packet( out, &pkt )) )
141         log_error("build_packet failed: %s\n", g10_errstr(rc) );
142
143     /* finish the stuff */
144     iobuf_close(inp);
145     iobuf_close(out); /* fixme: check returncode */
146     pt->buf = NULL;
147     free_packet(&pkt);
148     m_free(cfx.dek);
149     return rc;
150 }
151
152 /****************
153  * Encrypt the file with the given userids (or ask if none
154  * is supplied).
155  */
156 int
157 encode_crypt( const char *filename, STRLIST remusr )
158 {
159     IOBUF inp = NULL, out = NULL;
160     PACKET pkt;
161     PKT_plaintext *pt;
162     int rc = 0;
163     u32 filesize;
164     cipher_filter_context_t cfx;
165     armor_filter_context_t afx;
166     compress_filter_context_t zfx;
167     PKC_LIST pkc_list, pkc_rover;
168
169     memset( &cfx, 0, sizeof cfx);
170     memset( &afx, 0, sizeof afx);
171     memset( &zfx, 0, sizeof zfx);
172
173     if( (rc=build_pkc_list( remusr, &pkc_list)) )
174         return rc;
175
176     /* prepare iobufs */
177     if( !(inp = iobuf_open(filename)) ) {
178         log_error("can't open %s: %s\n", filename? filename: "[stdin]",
179                                         strerror(errno) );
180         rc = G10ERR_OPEN_FILE;
181         goto leave;
182     }
183     else if( opt.verbose )
184         log_error("reading from '%s'\n", filename? filename: "[stdin]");
185
186     if( !(out = open_outfile( filename, opt.armor? 1:0 )) ) {
187         rc = G10ERR_CREATE_FILE;  /* or user said: do not overwrite */
188         goto leave;
189     }
190
191     if( opt.armor )
192         iobuf_push_filter( out, armor_filter, &afx );
193
194     write_comment( out, "#Created by G10 pre-release " VERSION );
195
196     if( opt.compress )
197         iobuf_push_filter( out, compress_filter, &zfx );
198
199     /* create a session key */
200     cfx.dek = m_alloc_secure( sizeof *cfx.dek );
201     cfx.dek->algo = DEFAULT_CIPHER_ALGO;
202     make_session_key( cfx.dek );
203     if( DBG_CIPHER )
204         log_hexdump("DEK is: ", cfx.dek->key, cfx.dek->keylen );
205
206     /* loop over all public key certificates */
207     for( pkc_rover=pkc_list; pkc_rover; pkc_rover = pkc_rover->next ) {
208         PKT_public_cert *pkc;
209         PKT_pubkey_enc  *enc;
210
211         pkc = pkc_rover->pkc;
212         enc = m_alloc_clear( sizeof *enc );
213         enc->pubkey_algo = pkc->pubkey_algo;
214         if( enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL )
215             g10_elg_encrypt( pkc, enc, cfx.dek );
216         else if( enc->pubkey_algo == PUBKEY_ALGO_RSA )
217             g10_rsa_encrypt( pkc, enc, cfx.dek );
218         else
219             log_bug(NULL);
220         /* and write it */
221         init_packet(&pkt);
222         pkt.pkttype = PKT_PUBKEY_ENC;
223         pkt.pkt.pubkey_enc = enc;
224         rc = build_packet( out, &pkt );
225         free_pubkey_enc(enc);
226         if( rc ) {
227             log_error("build pubkey_enc packet failed: %s\n", g10_errstr(rc) );
228             goto leave;
229         }
230     }
231
232     /* setup the inner packet */
233     if( filename ) {
234         pt = m_alloc( sizeof *pt + strlen(filename) - 1 );
235         pt->namelen = strlen(filename);
236         memcpy(pt->name, filename, pt->namelen );
237         if( !(filesize = iobuf_get_filelength(inp)) )
238             log_info("warning: '%s' is an empty file\n", filename );
239     }
240     else { /* no filename */
241         pt = m_alloc( sizeof *pt - 1 );
242         pt->namelen = 0;
243         filesize = 0; /* stdin */
244     }
245     pt->timestamp = make_timestamp();
246     pt->mode = 'b';
247     pt->len = filesize;
248     pt->buf = inp;
249     init_packet(&pkt);
250     pkt.pkttype = PKT_PLAINTEXT;
251     pkt.pkt.plaintext = pt;
252     cfx.datalen = filesize? calc_packet_length( &pkt ) : 0;
253
254     /* register the cipher filter */
255     iobuf_push_filter( out, cipher_filter, &cfx );
256
257     /* do the work */
258     if( (rc = build_packet( out, &pkt )) )
259         log_error("build_packet failed: %s\n", g10_errstr(rc) );
260
261     /* finish the stuff */
262   leave:
263     iobuf_close(inp);
264     if( rc )
265         iobuf_cancel(out);
266     else
267         iobuf_close(out); /* fixme: check returncode */
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  #if 0
280 int
281 encrypt_filter( void *opaque, int control,
282                IOBUF a, byte *buf, size_t *ret_len)
283 {
284     size_t size = *ret_len;
285     encrypt_filter_context_t *efx = opaque;
286     int rc=0;
287
288     if( control == IOBUFCTRL_UNDERFLOW ) { /* decrypt */
289         log_bug(NULL); /* not used */
290     }
291     else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */
292     }
293     else if( control == IOBUFCTRL_FREE ) {
294     }
295     else if( control == IOBUFCTRL_DESC ) {
296         *(char**)buf = "encrypt_filter";
297     }
298     return rc;
299 }
300   #endif
301