~ubuntu-branches/ubuntu/jaunty/gnupg2/jaunty-security

« back to all changes in this revision

Viewing changes to g10/encr-data.c

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Viehmann
  • Date: 2008-10-04 10:25:53 UTC
  • mfrom: (5.1.15 intrepid)
  • Revision ID: james.westby@ubuntu.com-20081004102553-fv62pp8dsitxli47
Tags: 2.0.9-3.1
* Non-maintainer upload.
* agent/gpg-agent.c: Deinit the threading library before exec'ing
  the command to run in --daemon mode. And because that still doesn't
  restore the sigprocmask, do that manually. Closes: #499569

Show diffs side-by-side

added added

removed removed

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