Changeset View
Changeset View
Standalone View
Standalone View
encr-data.c
/* encr-data.c - process an encrypted data packet | /* encr-data.c - process an encrypted data packet | ||||
* Copyright (C) 1998, 1999, 2000, 2001, 2005 Free Software Foundation, Inc. | * Copyright (C) 1998, 1999, 2000, 2001, 2005, | ||||
* 2006 Free Software Foundation, Inc. | |||||
* | * | ||||
* This file is part of GnuPG. | * This file is part of GnuPG. | ||||
* | * | ||||
Context not available. | |||||
typedef struct { | typedef struct { | ||||
CIPHER_HANDLE cipher_hd; | CIPHER_HANDLE cipher_hd; | ||||
MD_HANDLE mdc_hash; | MD_HANDLE mdc_hash; | ||||
char defer[20]; | char defer[22]; | ||||
int defer_filled; | int defer_filled; | ||||
int eof_seen; | int eof_seen; | ||||
} decode_filter_ctx_t; | } decode_filter_ctx_t; | ||||
Context not available. | |||||
if( ed->mdc_method && dfx.eof_seen == 2 ) | if( ed->mdc_method && dfx.eof_seen == 2 ) | ||||
rc = G10ERR_INVALID_PACKET; | rc = G10ERR_INVALID_PACKET; | ||||
else if( ed->mdc_method ) { /* check the mdc */ | else if( ed->mdc_method ) { /* check the mdc */ | ||||
/* We used to let parse-packet.c handle the MDC packet but | |||||
this turned out to be a problem with compressed packets: | |||||
With old style packets there is no length information | |||||
available and the decompressor uses an implicit end. | |||||
However we can't know this implicit end beforehand (:-) and | |||||
thus may feed the decompressor with more bytes than | |||||
actually needed. It would be possible to unread the extra | |||||
bytes but due to our weird iobuf system any unread is non | |||||
reliable due to filters already popped off. The easy and | |||||
sane solution is to care about the MDC packet only here and | |||||
never pass it to the packet parser. Fortunatley the | |||||
OpenPGP spec requires a strict format for the MDC packet so | |||||
that we know that 22 bytes are appended. */ | |||||
int datalen = md_digest_length( ed->mdc_method ); | int datalen = md_digest_length( ed->mdc_method ); | ||||
cipher_decrypt( dfx.cipher_hd, dfx.defer, dfx.defer, 20); | cipher_decrypt( dfx.cipher_hd, dfx.defer, dfx.defer, 22); | ||||
md_write (dfx.mdc_hash, dfx.defer, 2); | |||||
md_final( dfx.mdc_hash ); | md_final( dfx.mdc_hash ); | ||||
if( datalen != 20 | if (dfx.defer[0] != '\xd3' || dfx.defer[1] != '\x14' ) { | ||||
|| memcmp(md_read( dfx.mdc_hash, 0 ), dfx.defer, datalen) ) | log_error("mdc_packet with invalid encoding\n"); | ||||
rc = G10ERR_INVALID_PACKET; | |||||
} | |||||
else if ( datalen != 20 | |||||
|| memcmp(md_read( dfx.mdc_hash, 0 ), dfx.defer+2, datalen) ) | |||||
rc = G10ERR_BAD_SIGN; | rc = G10ERR_BAD_SIGN; | ||||
/*log_hexdump("MDC calculated:", md_read( dfx.mdc_hash, 0), datalen);*/ | /*log_hexdump("MDC calculated:", md_read( dfx.mdc_hash, 0), datalen);*/ | ||||
/*log_hexdump("MDC message :", dfx.defer, 20);*/ | /*log_hexdump("MDC message :", dfx.defer, 20);*/ | ||||
Context not available. | |||||
} | } | ||||
else if( control == IOBUFCTRL_UNDERFLOW ) { | else if( control == IOBUFCTRL_UNDERFLOW ) { | ||||
assert(a); | assert(a); | ||||
assert( size > 40 ); | assert( size > 44 ); | ||||
/* get at least 20 bytes and put it somewhere ahead in the buffer */ | /* get at least 20 bytes and put it somewhere ahead in the buffer */ | ||||
for(n=20; n < 40 ; n++ ) { | for(n=22; n < 44 ; n++ ) { | ||||
if( (c = iobuf_get(a)) == -1 ) | if( (c = iobuf_get(a)) == -1 ) | ||||
break; | break; | ||||
buf[n] = c; | buf[n] = c; | ||||
} | } | ||||
if( n == 40 ) { | if( n == 44 ) { | ||||
/* we have enough stuff - flush the deferred stuff */ | /* we have enough stuff - flush the deferred stuff */ | ||||
/* (we have asserted that the buffer is large enough) */ | /* (we have asserted that the buffer is large enough) */ | ||||
if( !dfx->defer_filled ) { /* the first time */ | if( !dfx->defer_filled ) { /* the first time */ | ||||
memcpy(buf, buf+20, 20 ); | memcpy(buf, buf+22, 22 ); | ||||
n = 20; | n = 22; | ||||
} | } | ||||
else { | else { | ||||
memcpy(buf, dfx->defer, 20 ); | memcpy(buf, dfx->defer, 22 ); | ||||
} | } | ||||
/* now fill up */ | /* now fill up */ | ||||
for(; n < size; n++ ) { | for(; n < size; n++ ) { | ||||
Context not available. | |||||
break; | break; | ||||
buf[n] = c; | buf[n] = c; | ||||
} | } | ||||
/* move the last 20 bytes back to the defer buffer */ | /* Move the last 22 bytes back to the defer buffer. */ | ||||
/* (okay, we are wasting 20 bytes of supplied buffer) */ | /* (okay, we are wasting 22 bytes of supplied buffer) */ | ||||
n -= 20; | n -= 22; | ||||
memcpy( dfx->defer, buf+n, 20 ); | memcpy( dfx->defer, buf+n, 22 ); | ||||
dfx->defer_filled = 1; | dfx->defer_filled = 1; | ||||
} | } | ||||
else if( !dfx->defer_filled ) { /* eof seen buf empty defer */ | else if( !dfx->defer_filled ) { /* eof seen buf empty defer */ | ||||
/* this is bad because there is an incomplete hash */ | /* this is bad because there is an incomplete hash */ | ||||
n -= 20; | n -= 22; | ||||
memcpy(buf, buf+20, n ); | memcpy(buf, buf+22, n ); | ||||
dfx->eof_seen = 2; /* eof with incomplete hash */ | dfx->eof_seen = 2; /* eof with incomplete hash */ | ||||
} | } | ||||
else { /* eof seen */ | else { /* eof seen */ | ||||
memcpy(buf, dfx->defer, 20 ); | memcpy (buf, dfx->defer, 22 ); | ||||
n -= 20; | n -= 22; | ||||
memcpy( dfx->defer, buf+n, 20 ); | memcpy( dfx->defer, buf+n, 22 ); | ||||
dfx->eof_seen = 1; /* normal eof */ | dfx->eof_seen = 1; /* normal eof */ | ||||
} | } | ||||
Context not available. |