Migrated more stuff to doc/
[gnupg.git] / g10 / encr-data.c
1 /* encr-data.c -  process an encrypted data packet
2  * Copyright (C) 1998, 1999, 2000, 2001, 2005,
3  *               2006 Free Software Foundation, Inc.
4  *
5  * This file is part of GnuPG.
6  *
7  * GnuPG is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * GnuPG is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20  * USA.
21  */
22
23 #include <config.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <assert.h>
28
29 #include "gpg.h"
30 #include "util.h"
31 #include "packet.h"
32 #include "cipher.h"
33 #include "options.h"
34 #include "i18n.h"
35
36
37 static int mdc_decode_filter( void *opaque, int control, IOBUF a,
38                                               byte *buf, size_t *ret_len);
39 static int decode_filter( void *opaque, int control, IOBUF a,
40                                         byte *buf, size_t *ret_len);
41
42 typedef struct 
43 {
44   gcry_cipher_hd_t cipher_hd;
45   gcry_md_hd_t mdc_hash;
46   char defer[20];
47   int  defer_filled;
48   int  eof_seen;
49 } decode_filter_ctx_t;
50
51
52 /****************
53  * Decrypt the data, specified by ED with the key DEK.
54  */
55 int
56 decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
57 {
58     decode_filter_ctx_t dfx;
59     byte *p;
60     int rc=0, c, i;
61     byte temp[32];
62     unsigned blocksize;
63     unsigned nprefix;
64
65     memset( &dfx, 0, sizeof dfx );
66     if( opt.verbose && !dek->algo_info_printed ) {
67         const char *s = gcry_cipher_algo_name (dek->algo);
68         if (s && *s)
69             log_info(_("%s encrypted data\n"), s );
70         else
71             log_info(_("encrypted with unknown algorithm %d\n"), dek->algo );
72         dek->algo_info_printed = 1;
73     }
74     rc = openpgp_cipher_test_algo (dek->algo);
75     if (rc)
76         goto leave;
77     blocksize = gcry_cipher_get_algo_blklen (dek->algo);
78     if( !blocksize || blocksize > 16 )
79         log_fatal("unsupported blocksize %u\n", blocksize );
80     nprefix = blocksize;
81     if( ed->len && ed->len < (nprefix+2) )
82         BUG();
83
84     if( ed->mdc_method ) {
85         if (gcry_md_open (&dfx.mdc_hash, ed->mdc_method, 0 ))
86             BUG ();
87         if ( DBG_HASHING )
88             gcry_md_start_debug (dfx.mdc_hash, "checkmdc");
89     }
90
91     rc = gcry_cipher_open (&dfx.cipher_hd, dek->algo,
92                            GCRY_CIPHER_MODE_CFB,
93                            (GCRY_CIPHER_SECURE
94                             | ((ed->mdc_method || dek->algo >= 100)?
95                                0 : GCRY_CIPHER_ENABLE_SYNC)));
96     if (rc)
97       {
98         /* We should never get an error here cause we already checked
99          * that the algorithm is available.  */
100         BUG();
101       }
102
103
104     /* log_hexdump( "thekey", dek->key, dek->keylen );*/
105     rc = gcry_cipher_setkey (dfx.cipher_hd, dek->key, dek->keylen);
106     if ( gpg_err_code (rc) == GPG_ERR_WEAK_KEY )
107       {
108         log_info(_("WARNING: message was encrypted with"
109                    " a weak key in the symmetric cipher.\n"));
110         rc=0;
111       }
112     else if( rc )
113       {
114         log_error("key setup failed: %s\n", g10_errstr(rc) );
115         goto leave;
116       
117       }
118     if (!ed->buf) {
119         log_error(_("problem handling encrypted packet\n"));
120         goto leave;
121     }
122
123     gcry_cipher_setiv (dfx.cipher_hd, NULL, 0);
124
125     if( ed->len ) {
126         for(i=0; i < (nprefix+2) && ed->len; i++, ed->len-- ) {
127             if( (c=iobuf_get(ed->buf)) == -1 )
128                 break;
129             else
130                 temp[i] = c;
131         }
132     }
133     else {
134         for(i=0; i < (nprefix+2); i++ )
135             if( (c=iobuf_get(ed->buf)) == -1 )
136                 break;
137             else
138                 temp[i] = c;
139     }
140
141     gcry_cipher_decrypt (dfx.cipher_hd, temp, nprefix+2, NULL, 0);
142     gcry_cipher_sync (dfx.cipher_hd);
143     p = temp;
144 /* log_hexdump( "prefix", temp, nprefix+2 ); */
145     if(dek->symmetric
146        && (p[nprefix-2] != p[nprefix] || p[nprefix-1] != p[nprefix+1]) )
147       {
148         rc = GPG_ERR_BAD_KEY;
149         goto leave;
150       }
151
152     if( dfx.mdc_hash )
153         gcry_md_write (dfx.mdc_hash, temp, nprefix+2);
154
155     if( ed->mdc_method )
156         iobuf_push_filter( ed->buf, mdc_decode_filter, &dfx );
157     else
158         iobuf_push_filter( ed->buf, decode_filter, &dfx );
159
160     proc_packets( procctx, ed->buf );
161     ed->buf = NULL;
162     if( ed->mdc_method && dfx.eof_seen == 2 )
163         rc = gpg_error (GPG_ERR_INV_PACKET);
164     else if( ed->mdc_method ) { /* check the mdc */
165         int datalen = gcry_md_get_algo_dlen (ed->mdc_method);
166
167         gcry_cipher_decrypt (dfx.cipher_hd, dfx.defer, 20, NULL, 0);
168         gcry_md_final (dfx.mdc_hash);
169         if (datalen != 20
170             || memcmp (gcry_md_read( dfx.mdc_hash, 0 ), dfx.defer, datalen) )
171           rc = gpg_error (GPG_ERR_BAD_SIGNATURE);
172         /*log_hexdump("MDC calculated:", md_read( dfx.mdc_hash, 0), datalen);*/
173         /*log_hexdump("MDC message   :", dfx.defer, 20);*/
174     }
175     
176
177   leave:
178     gcry_cipher_close (dfx.cipher_hd);
179     gcry_md_close (dfx.mdc_hash);
180     return rc;
181 }
182
183
184
185 /* I think we should merge this with cipher_filter */
186 static int
187 mdc_decode_filter( void *opaque, int control, IOBUF a,
188                                               byte *buf, size_t *ret_len)
189 {
190     decode_filter_ctx_t *dfx = opaque;
191     size_t n, size = *ret_len;
192     int rc = 0;
193     int c;
194
195     if( control == IOBUFCTRL_UNDERFLOW && dfx->eof_seen ) {
196         *ret_len = 0;
197         rc = -1;
198     }
199     else if( control == IOBUFCTRL_UNDERFLOW ) {
200         assert(a);
201         assert( size > 40 );
202
203         /* get at least 20 bytes and put it somewhere ahead in the buffer */
204         for(n=20; n < 40 ; n++ ) {
205             if( (c = iobuf_get(a)) == -1 )
206                 break;
207             buf[n] = c;
208         }
209         if( n == 40 ) {
210             /* we have enough stuff - flush the deferred stuff */
211             /* (we have asserted that the buffer is large enough) */
212             if( !dfx->defer_filled ) { /* the first time */
213                 memcpy(buf, buf+20, 20 );
214                 n = 20;
215             }
216             else {
217                 memcpy(buf, dfx->defer, 20 );
218             }
219             /* now fill up */
220             for(; n < size; n++ ) {
221                 if( (c = iobuf_get(a)) == -1 )
222                     break;
223                 buf[n] = c;
224             }
225             /* move the last 20 bytes back to the defer buffer */
226             /* (okay, we are wasting 20 bytes of supplied buffer) */
227             n -= 20;
228             memcpy( dfx->defer, buf+n, 20 );
229             dfx->defer_filled = 1;
230         }
231         else if( !dfx->defer_filled ) { /* eof seen buf empty defer */
232             /* this is bad because there is an incomplete hash */
233             n -= 20;
234             memcpy(buf, buf+20, n );
235             dfx->eof_seen = 2; /* eof with incomplete hash */
236         }
237         else { /* eof seen */
238             memcpy(buf, dfx->defer, 20 );
239             n -= 20;
240             memcpy( dfx->defer, buf+n, 20 );
241             dfx->eof_seen = 1; /* normal eof */
242         }
243
244         if( n ) {
245             gcry_cipher_decrypt (dfx->cipher_hd, buf, n, NULL, 0);
246             gcry_md_write (dfx->mdc_hash, buf, n);
247         }
248         else {
249             assert( dfx->eof_seen );
250             rc = -1; /* eof */
251         }
252         *ret_len = n;
253     }
254     else if( control == IOBUFCTRL_DESC ) {
255         *(char**)buf = "mdc_decode_filter";
256     }
257     return rc;
258 }
259
260 static int
261 decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len)
262 {
263     decode_filter_ctx_t *fc = opaque;
264     size_t n, size = *ret_len;
265     int rc = 0;
266
267     if( control == IOBUFCTRL_UNDERFLOW ) {
268         assert(a);
269         n = iobuf_read( a, buf, size );
270         if( n == -1 ) n = 0;
271         if( n )
272             gcry_cipher_decrypt (fc->cipher_hd, buf, n, NULL, 0);
273         else
274             rc = -1; /* eof */
275         *ret_len = n;
276     }
277     else if( control == IOBUFCTRL_DESC ) {
278         *(char**)buf = "decode_filter";
279     }
280     return rc;
281 }
282