Fixes for CVE-2006-6235
[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 decode_filter_context_s
43 {
44   gcry_cipher_hd_t cipher_hd;
45   gcry_md_hd_t mdc_hash;
46   char defer[22];
47   int  defer_filled;
48   int  eof_seen;
49   int  refcount;
50 } *decode_filter_ctx_t;
51
52
53 /* Helper to release the decode context.  */
54 static void
55 release_dfx_context (decode_filter_ctx_t dfx)
56 {
57   if (!dfx)
58     return;
59
60   assert (dfx->refcount);
61   if ( !--dfx->refcount )
62     {
63       gcry_cipher_close (dfx->cipher_hd);
64       dfx->cipher_hd = NULL;
65       gcry_md_close (dfx->mdc_hash);
66       dfx->mdc_hash = NULL;
67       xfree (dfx);
68     }
69 }
70
71
72
73 /****************
74  * Decrypt the data, specified by ED with the key DEK.
75  */
76 int
77 decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
78 {
79   decode_filter_ctx_t dfx;
80   byte *p;
81   int rc=0, c, i;
82   byte temp[32];
83   unsigned blocksize;
84   unsigned nprefix;
85   
86   dfx = xtrycalloc (1, sizeof *dfx);
87   if (!dfx)
88     return gpg_error_from_syserror ();
89   dfx->refcount = 1;
90
91   if ( opt.verbose && !dek->algo_info_printed )
92     {
93       const char *s = gcry_cipher_algo_name (dek->algo);
94       if (s && *s)
95         log_info(_("%s encrypted data\n"), s );
96       else
97         log_info(_("encrypted with unknown algorithm %d\n"), dek->algo );
98       dek->algo_info_printed = 1;
99     }
100   rc = openpgp_cipher_test_algo (dek->algo);
101   if (rc)
102     goto leave;
103   blocksize = gcry_cipher_get_algo_blklen (dek->algo);
104   if ( !blocksize || blocksize > 16 )
105     log_fatal ("unsupported blocksize %u\n", blocksize );
106   nprefix = blocksize;
107   if ( ed->len && ed->len < (nprefix+2) )
108     BUG();
109
110   if ( ed->mdc_method ) 
111     {
112       if (gcry_md_open (&dfx->mdc_hash, ed->mdc_method, 0 ))
113         BUG ();
114       if ( DBG_HASHING )
115         gcry_md_start_debug (dfx->mdc_hash, "checkmdc");
116     }
117
118   rc = gcry_cipher_open (&dfx->cipher_hd, dek->algo,
119                          GCRY_CIPHER_MODE_CFB,
120                          (GCRY_CIPHER_SECURE
121                           | ((ed->mdc_method || dek->algo >= 100)?
122                              0 : GCRY_CIPHER_ENABLE_SYNC)));
123   if (rc)
124     {
125       /* We should never get an error here cause we already checked
126        * that the algorithm is available.  */
127       BUG();
128     }
129
130
131   /* log_hexdump( "thekey", dek->key, dek->keylen );*/
132   rc = gcry_cipher_setkey (dfx->cipher_hd, dek->key, dek->keylen);
133   if ( gpg_err_code (rc) == GPG_ERR_WEAK_KEY )
134     {
135       log_info(_("WARNING: message was encrypted with"
136                  " a weak key in the symmetric cipher.\n"));
137       rc=0;
138     }
139   else if( rc )
140     {
141       log_error("key setup failed: %s\n", g10_errstr(rc) );
142       goto leave;
143     }
144
145   if (!ed->buf) 
146     {
147       log_error(_("problem handling encrypted packet\n"));
148       goto leave;
149     }
150
151   gcry_cipher_setiv (dfx->cipher_hd, NULL, 0);
152
153   if ( ed->len )
154     {
155       for (i=0; i < (nprefix+2) && ed->len; i++, ed->len-- ) 
156         {
157           if ( (c=iobuf_get(ed->buf)) == -1 )
158             break;
159           else
160             temp[i] = c;
161         }
162     }
163   else 
164     {
165       for (i=0; i < (nprefix+2); i++ )
166         if ( (c=iobuf_get(ed->buf)) == -1 )
167           break;
168         else
169           temp[i] = c;
170     }
171   
172   gcry_cipher_decrypt (dfx->cipher_hd, temp, nprefix+2, NULL, 0);
173   gcry_cipher_sync (dfx->cipher_hd);
174   p = temp;
175   /* log_hexdump( "prefix", temp, nprefix+2 ); */
176   if (dek->symmetric
177       && (p[nprefix-2] != p[nprefix] || p[nprefix-1] != p[nprefix+1]) )
178     {
179       rc = gpg_error (GPG_ERR_BAD_KEY);
180       goto leave;
181     }
182   
183   if ( dfx->mdc_hash )
184     gcry_md_write (dfx->mdc_hash, temp, nprefix+2);
185
186   dfx->refcount++;
187   if ( ed->mdc_method )
188     iobuf_push_filter ( ed->buf, mdc_decode_filter, dfx );
189   else
190     iobuf_push_filter ( ed->buf, decode_filter, dfx );
191
192   proc_packets ( procctx, ed->buf );
193   ed->buf = NULL;
194   if ( ed->mdc_method && dfx->eof_seen == 2 )
195     rc = gpg_error (GPG_ERR_INV_PACKET);
196   else if ( ed->mdc_method )
197     { 
198       /* We used to let parse-packet.c handle the MDC packet but this
199          turned out to be a problem with compressed packets: With old
200          style packets there is no length information available and
201          the decompressor uses an implicit end.  However we can't know
202          this implicit end beforehand (:-) and thus may feed the
203          decompressor with more bytes than actually needed.  It would
204          be possible to unread the extra bytes but due to our weird
205          iobuf system any unread is non reliable due to filters
206          already popped off.  The easy and sane solution is to care
207          about the MDC packet only here and never pass it to the
208          packet parser.  Fortunatley the OpenPGP spec requires a
209          strict format for the MDC packet so that we know that 22
210          bytes are appended.  */
211       int datalen = gcry_md_get_algo_dlen (ed->mdc_method);
212
213       assert (dfx->cipher_hd);
214       assert (dfx->mdc_hash);
215       gcry_cipher_decrypt (dfx->cipher_hd, dfx->defer, 22, NULL, 0);
216       gcry_md_write (dfx->mdc_hash, dfx->defer, 2);
217       gcry_md_final (dfx->mdc_hash);
218
219       if (dfx->defer[0] != '\xd3' || dfx->defer[1] != '\x14' )
220         {
221           log_error("mdc_packet with invalid encoding\n");
222           rc = gpg_error (GPG_ERR_INV_PACKET);
223         }
224       else if (datalen != 20
225                || memcmp (gcry_md_read (dfx->mdc_hash, 0),
226                           dfx->defer+2,datalen ))
227         rc = gpg_error (GPG_ERR_BAD_SIGNATURE);
228       /* log_printhex("MDC message:", dfx->defer, 22); */
229       /* log_printhex("MDC calc:", gcry_md_read (dfx->mdc_hash,0), datalen); */
230     }
231   
232   
233  leave:
234   release_dfx_context (dfx);
235   return rc;
236 }
237
238
239
240 /* I think we should merge this with cipher_filter */
241 static int
242 mdc_decode_filter (void *opaque, int control, IOBUF a,
243                    byte *buf, size_t *ret_len)
244 {
245   decode_filter_ctx_t dfx = opaque;
246   size_t n, size = *ret_len;
247   int rc = 0;
248   int c;
249   
250   if ( control == IOBUFCTRL_UNDERFLOW && dfx->eof_seen )
251     {
252       *ret_len = 0;
253       rc = -1;
254     }
255   else if( control == IOBUFCTRL_UNDERFLOW )
256     {
257       assert (a);
258       assert ( size > 44 );
259       
260       /* Get at least 22 bytes and put it somewhere ahead in the buffer. */
261       for (n=22; n < 44 ; n++ )
262         {
263           if( (c = iobuf_get(a)) == -1 )
264             break;
265           buf[n] = c;
266         }
267       if ( n == 44 ) 
268         {
269           /* We have enough stuff - flush the deferred stuff.  */
270           /* (we asserted that the buffer is large enough) */
271           if ( !dfx->defer_filled )  /* First time. */
272             {
273               memcpy (buf, buf+22, 22 );
274               n = 22;
275             }
276           else
277             {
278               memcpy (buf, dfx->defer, 22 );
279             }
280           /* Now fill up. */
281           for (; n < size; n++ ) 
282             {
283               if ( (c = iobuf_get(a)) == -1 )
284                 break;
285               buf[n] = c;
286             }
287           /* Move the last 22 bytes back to the defer buffer. */
288           /* (right, we are wasting 22 bytes of the supplied buffer.) */
289           n -= 22;
290           memcpy (dfx->defer, buf+n, 22 );
291           dfx->defer_filled = 1;
292         }
293       else if ( !dfx->defer_filled )  /* EOF seen but empty defer buffer. */
294         {
295           /* This is bad because it means an incomplete hash. */
296           n -= 22;
297           memcpy (buf, buf+22, n );
298           dfx->eof_seen = 2; /* EOF with incomplete hash.  */
299         }
300       else  /* EOF seen (i.e. read less than 22 bytes). */
301         {
302           memcpy (buf, dfx->defer, 22 );
303           n -= 22;
304           memcpy (dfx->defer, buf+n, 22 );
305           dfx->eof_seen = 1; /* Normal EOF. */
306         }
307
308       if ( n )
309         {
310           if ( dfx->cipher_hd )
311             gcry_cipher_decrypt (dfx->cipher_hd, buf, n, NULL, 0);
312           if ( dfx->mdc_hash )
313             gcry_md_write (dfx->mdc_hash, buf, n);
314         }
315       else
316         {
317           assert ( dfx->eof_seen );
318           rc = -1; /* eof */
319         }
320       *ret_len = n;
321     }
322   else if ( control == IOBUFCTRL_FREE ) 
323     {
324       release_dfx_context (dfx);
325     }
326   else if ( control == IOBUFCTRL_DESC ) 
327     {
328       *(char**)buf = "mdc_decode_filter";
329     }
330   return rc;
331 }
332
333
334 static int
335 decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len)
336 {
337   decode_filter_ctx_t fc = opaque;
338   size_t n, size = *ret_len;
339   int rc = 0;
340   
341   if ( control == IOBUFCTRL_UNDERFLOW ) 
342     {
343       assert(a);
344       n = iobuf_read ( a, buf, size );
345       if ( n == -1 )
346         n = 0;
347       if ( n )
348         {
349           if (fc->cipher_hd)
350             gcry_cipher_decrypt (fc->cipher_hd, buf, n, NULL, 0);
351         }
352       else
353         rc = -1; /* EOF */
354       *ret_len = n;
355     }
356   else if ( control == IOBUFCTRL_FREE ) 
357     {
358       release_dfx_context (fc);
359     }
360   else if ( control == IOBUFCTRL_DESC )
361     {
362       *(char**)buf = "decode_filter";
363     }
364   return rc;
365 }
366