~ubuntu-branches/ubuntu/hardy/gnupg/hardy-updates

« back to all changes in this revision

Viewing changes to g10/encr-data.c

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook
  • Date: 2006-12-12 15:56:56 UTC
  • mto: This revision was merged to the branch mainline in revision 14.
  • Revision ID: james.westby@ubuntu.com-20061212155656-kk00wp4x0uq4tm1y
Tags: upstream-1.4.6
ImportĀ upstreamĀ versionĀ 1.4.6

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, 2005 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
 *
41
42
typedef struct {
42
43
    CIPHER_HANDLE cipher_hd;
43
44
    MD_HANDLE mdc_hash;
44
 
    char defer[20];
 
45
    char defer[22];
45
46
    int  defer_filled;
46
47
    int  eof_seen;
47
 
} decode_filter_ctx_t;
 
48
    int  refcount;
 
49
} *decode_filter_ctx_t;
 
50
 
 
51
 
 
52
/* Helper to release the decode context.  */
 
53
static void
 
54
release_dfx_context (decode_filter_ctx_t dfx)
 
55
{
 
56
  if (!dfx)
 
57
    return;
 
58
 
 
59
  assert (dfx->refcount);
 
60
  if ( !--dfx->refcount )
 
61
    {
 
62
      cipher_close (dfx->cipher_hd);
 
63
      dfx->cipher_hd = NULL;
 
64
      md_close (dfx->mdc_hash);
 
65
      dfx->mdc_hash = NULL;
 
66
      xfree (dfx);
 
67
    }
 
68
}
48
69
 
49
70
 
50
71
/****************
60
81
    unsigned blocksize;
61
82
    unsigned nprefix;
62
83
 
63
 
    memset( &dfx, 0, sizeof dfx );
 
84
 
 
85
    dfx = xcalloc (1, sizeof *dfx);
 
86
    dfx->refcount = 1;
 
87
 
64
88
    if( opt.verbose && !dek->algo_info_printed ) {
65
89
        const char *s = cipher_algo_to_string( dek->algo );
66
90
        if( s )
79
103
        BUG();
80
104
 
81
105
    if( ed->mdc_method ) {
82
 
        dfx.mdc_hash = md_open( ed->mdc_method, 0 );
 
106
        dfx->mdc_hash = md_open ( ed->mdc_method, 0 );
83
107
        if ( DBG_HASHING )
84
 
            md_start_debug(dfx.mdc_hash, "checkmdc");
 
108
            md_start_debug (dfx->mdc_hash, "checkmdc");
85
109
    }
86
 
    dfx.cipher_hd = cipher_open( dek->algo,
87
 
                                 ed->mdc_method? CIPHER_MODE_CFB
88
 
                                               : CIPHER_MODE_AUTO_CFB, 1 );
 
110
    dfx->cipher_hd = cipher_open ( dek->algo,
 
111
                                   ed->mdc_method? CIPHER_MODE_CFB
 
112
                                                 : CIPHER_MODE_AUTO_CFB, 1 );
89
113
    /* log_hexdump( "thekey", dek->key, dek->keylen );*/
90
 
    rc = cipher_setkey( dfx.cipher_hd, dek->key, dek->keylen );
 
114
    rc = cipher_setkey ( dfx->cipher_hd, dek->key, dek->keylen );
91
115
    if( rc == G10ERR_WEAK_KEY )
92
116
      {
93
117
        log_info(_("WARNING: message was encrypted with"
105
129
        goto leave;
106
130
    }
107
131
 
108
 
    cipher_setiv( dfx.cipher_hd, NULL, 0 );
 
132
    cipher_setiv ( dfx->cipher_hd, NULL, 0 );
109
133
 
110
134
    if( ed->len ) {
111
135
        for(i=0; i < (nprefix+2) && ed->len; i++, ed->len-- ) {
122
146
            else
123
147
                temp[i] = c;
124
148
    }
125
 
    cipher_decrypt( dfx.cipher_hd, temp, temp, nprefix+2);
126
 
    cipher_sync( dfx.cipher_hd );
 
149
    cipher_decrypt ( dfx->cipher_hd, temp, temp, nprefix+2);
 
150
    cipher_sync ( dfx->cipher_hd );
127
151
    p = temp;
128
152
/* log_hexdump( "prefix", temp, nprefix+2 ); */
129
153
    if(dek->symmetric
133
157
        goto leave;
134
158
      }
135
159
 
136
 
    if( dfx.mdc_hash )
137
 
        md_write( dfx.mdc_hash, temp, nprefix+2 );
 
160
    if ( dfx->mdc_hash )
 
161
        md_write ( dfx->mdc_hash, temp, nprefix+2 );
138
162
 
139
 
    if( ed->mdc_method )
140
 
        iobuf_push_filter( ed->buf, mdc_decode_filter, &dfx );
 
163
    dfx->refcount++;
 
164
    if ( ed->mdc_method )
 
165
        iobuf_push_filter( ed->buf, mdc_decode_filter, dfx );
141
166
    else
142
 
        iobuf_push_filter( ed->buf, decode_filter, &dfx );
 
167
        iobuf_push_filter( ed->buf, decode_filter, dfx );
143
168
 
144
169
    proc_packets( procctx, ed->buf );
145
170
    ed->buf = NULL;
146
 
    if( ed->mdc_method && dfx.eof_seen == 2 )
 
171
    if( ed->mdc_method && dfx->eof_seen == 2 )
147
172
        rc = G10ERR_INVALID_PACKET;
148
173
    else if( ed->mdc_method ) { /* check the mdc */
 
174
        /* We used to let parse-packet.c handle the MDC packet but
 
175
           this turned out to be a problem with compressed packets:
 
176
           With old style packets there is no length information
 
177
           available and the decompressor uses an implicit end.
 
178
           However we can't know this implicit end beforehand (:-) and
 
179
           thus may feed the decompressor with more bytes than
 
180
           actually needed.  It would be possible to unread the extra
 
181
           bytes but due to our weird iobuf system any unread is non
 
182
           reliable due to filters already popped off.  The easy and
 
183
           sane solution is to care about the MDC packet only here and
 
184
           never pass it to the packet parser.  Fortunatley the
 
185
           OpenPGP spec requires a strict format for the MDC packet so
 
186
           that we know that 22 bytes are appended.  */
149
187
        int datalen = md_digest_length( ed->mdc_method );
150
188
 
151
 
        cipher_decrypt( dfx.cipher_hd, dfx.defer, dfx.defer, 20);
152
 
        md_final( dfx.mdc_hash );
153
 
        if( datalen != 20
154
 
            || memcmp(md_read( dfx.mdc_hash, 0 ), dfx.defer, datalen) )
 
189
        assert (dfx->cipher_hd);
 
190
        assert (dfx->mdc_hash);
 
191
        cipher_decrypt ( dfx->cipher_hd, dfx->defer, dfx->defer, 22);
 
192
        md_write ( dfx->mdc_hash, dfx->defer, 2);
 
193
        md_final ( dfx->mdc_hash );
 
194
        if (dfx->defer[0] != '\xd3' || dfx->defer[1] != '\x14' ) {
 
195
            log_error("mdc_packet with invalid encoding\n");
 
196
            rc = G10ERR_INVALID_PACKET;
 
197
        }
 
198
        else if ( datalen != 20
 
199
            || memcmp(md_read( dfx->mdc_hash, 0 ), dfx->defer+2, datalen) )
155
200
            rc = G10ERR_BAD_SIGN;
156
 
        /*log_hexdump("MDC calculated:", md_read( dfx.mdc_hash, 0), datalen);*/
157
 
        /*log_hexdump("MDC message   :", dfx.defer, 20);*/
 
201
        /*log_hexdump("MDC calculated:",md_read( dfx->mdc_hash, 0), datalen);*/
 
202
        /*log_hexdump("MDC message   :", dfx->defer, 20);*/
158
203
    }
159
204
    
160
205
 
161
206
  leave:
162
 
    cipher_close(dfx.cipher_hd);
163
 
    md_close( dfx.mdc_hash );
 
207
    release_dfx_context (dfx);
164
208
    return rc;
165
209
}
166
210
 
171
215
mdc_decode_filter( void *opaque, int control, IOBUF a,
172
216
                                              byte *buf, size_t *ret_len)
173
217
{
174
 
    decode_filter_ctx_t *dfx = opaque;
 
218
    decode_filter_ctx_t dfx = opaque;
175
219
    size_t n, size = *ret_len;
176
220
    int rc = 0;
177
221
    int c;
182
226
    }
183
227
    else if( control == IOBUFCTRL_UNDERFLOW ) {
184
228
        assert(a);
185
 
        assert( size > 40 );
 
229
        assert( size > 44 );
186
230
 
187
231
        /* get at least 20 bytes and put it somewhere ahead in the buffer */
188
 
        for(n=20; n < 40 ; n++ ) {
 
232
        for(n=22; n < 44 ; n++ ) {
189
233
            if( (c = iobuf_get(a)) == -1 )
190
234
                break;
191
235
            buf[n] = c;
192
236
        }
193
 
        if( n == 40 ) {
 
237
        if( n == 44 ) {
194
238
            /* we have enough stuff - flush the deferred stuff */
195
239
            /* (we have asserted that the buffer is large enough) */
196
240
            if( !dfx->defer_filled ) { /* the first time */
197
 
                memcpy(buf, buf+20, 20 );
198
 
                n = 20;
 
241
                memcpy(buf, buf+22, 22 );
 
242
                n = 22;
199
243
            }
200
244
            else {
201
 
                memcpy(buf, dfx->defer, 20 );
 
245
                memcpy(buf, dfx->defer, 22 );
202
246
            }
203
247
            /* now fill up */
204
248
            for(; n < size; n++ ) {
206
250
                    break;
207
251
                buf[n] = c;
208
252
            }
209
 
            /* move the last 20 bytes back to the defer buffer */
210
 
            /* (okay, we are wasting 20 bytes of supplied buffer) */
211
 
            n -= 20;
212
 
            memcpy( dfx->defer, buf+n, 20 );
 
253
            /* Move the last 22 bytes back to the defer buffer. */
 
254
            /* (okay, we are wasting 22 bytes of supplied buffer) */
 
255
            n -= 22;
 
256
            memcpy( dfx->defer, buf+n, 22 );
213
257
            dfx->defer_filled = 1;
214
258
        }
215
259
        else if( !dfx->defer_filled ) { /* eof seen buf empty defer */
216
260
            /* this is bad because there is an incomplete hash */
217
 
            n -= 20;
218
 
            memcpy(buf, buf+20, n );
 
261
            n -= 22;
 
262
            memcpy(buf, buf+22, n );
219
263
            dfx->eof_seen = 2; /* eof with incomplete hash */
220
264
        }
221
265
        else { /* eof seen */
222
 
            memcpy(buf, dfx->defer, 20 );
223
 
            n -= 20;
224
 
            memcpy( dfx->defer, buf+n, 20 );
 
266
            memcpy (buf, dfx->defer, 22 );
 
267
            n -= 22;
 
268
            memcpy( dfx->defer, buf+n, 22 );
225
269
            dfx->eof_seen = 1; /* normal eof */
226
270
        }
227
271
 
228
272
        if( n ) {
229
 
            cipher_decrypt( dfx->cipher_hd, buf, buf, n);
230
 
            md_write( dfx->mdc_hash, buf, n );
 
273
            if (dfx->cipher_hd)
 
274
                cipher_decrypt( dfx->cipher_hd, buf, buf, n);
 
275
            if (dfx->mdc_hash)
 
276
                md_write( dfx->mdc_hash, buf, n );
231
277
        }
232
278
        else {
233
279
            assert( dfx->eof_seen );
235
281
        }
236
282
        *ret_len = n;
237
283
    }
 
284
    else if ( control == IOBUFCTRL_FREE ) {
 
285
        release_dfx_context (dfx);
 
286
    }
238
287
    else if( control == IOBUFCTRL_DESC ) {
239
288
        *(char**)buf = "mdc_decode_filter";
240
289
    }
244
293
static int
245
294
decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len)
246
295
{
247
 
    decode_filter_ctx_t *fc = opaque;
 
296
    decode_filter_ctx_t fc = opaque;
248
297
    size_t n, size = *ret_len;
249
298
    int rc = 0;
250
299
 
252
301
        assert(a);
253
302
        n = iobuf_read( a, buf, size );
254
303
        if( n == -1 ) n = 0;
255
 
        if( n )
256
 
            cipher_decrypt( fc->cipher_hd, buf, buf, n);
 
304
        if( n ) {
 
305
            if (fc->cipher_hd)
 
306
                cipher_decrypt( fc->cipher_hd, buf, buf, n);
 
307
        }
257
308
        else
258
309
            rc = -1; /* eof */
259
310
        *ret_len = n;
260
311
    }
 
312
    else if ( control == IOBUFCTRL_FREE ) {
 
313
        release_dfx_context (fc);
 
314
    }
261
315
    else if( control == IOBUFCTRL_DESC ) {
262
316
        *(char**)buf = "decode_filter";
263
317
    }