2005-04-15 Marcus Brinkmann <marcus@g10code.de>
[gnupg.git] / g10 / encr-data.c
blob07440840481667ab05f060e1d1364aba3870645d
1 /* encr-data.c - process an encrypted data packet
2 * Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * 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 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * 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
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <assert.h>
27 #include "gpg.h"
28 #include "util.h"
29 #include "memory.h"
30 #include "packet.h"
31 #include "mpi.h"
32 #include "cipher.h"
33 #include "options.h"
34 #include "i18n.h"
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,
40 byte *buf, size_t *ret_len);
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;
51 /****************
52 * Decrypt the data, specified by ED with the key DEK.
54 int
55 decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
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;
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;
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();
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");
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)
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();
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;
108 if (!ed->buf) {
109 log_error(_("problem handling encrypted packet\n"));
110 goto leave;
113 gcry_cipher_setiv (dfx.cipher_hd, NULL, 0);
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;
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;
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;
139 if( dfx.mdc_hash )
140 gcry_md_write( dfx.mdc_hash, temp, nprefix+2 );
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 );
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);
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);*/
164 leave:
165 gcry_cipher_close(dfx.cipher_hd);
166 gcry_md_close ( dfx.mdc_hash );
167 return rc;
172 /* I think we should merge this with cipher_filter */
173 static int
174 mdc_decode_filter( void *opaque, int control, iobuf_t a,
175 byte *buf, size_t *ret_len)
177 decode_filter_ctx_t *dfx = opaque;
178 size_t n, size = *ret_len;
179 int rc = 0;
180 int c;
182 if( control == IOBUFCTRL_UNDERFLOW && dfx->eof_seen ) {
183 *ret_len = 0;
184 rc = -1;
186 else if( control == IOBUFCTRL_UNDERFLOW ) {
187 assert(a);
188 assert( size > 40 );
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;
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;
203 else {
204 memcpy(buf, dfx->defer, 20 );
206 /* now fill up */
207 for(; n < size; n++ ) {
208 if( (c = iobuf_get(a)) == -1 )
209 break;
210 buf[n] = c;
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;
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 */
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 */
231 if( n ) {
232 gcry_cipher_decrypt( dfx->cipher_hd, buf, n, NULL, 0);
233 gcry_md_write( dfx->mdc_hash, buf, n );
235 else {
236 assert( dfx->eof_seen );
237 rc = -1; /* eof */
239 *ret_len = n;
241 else if( control == IOBUFCTRL_DESC ) {
242 *(char**)buf = "mdc_decode_filter";
244 return rc;
247 static int
248 decode_filter( void *opaque, int control, iobuf_t a, byte *buf, size_t *ret_len)
250 decode_filter_ctx_t *fc = opaque;
251 size_t n, size = *ret_len;
252 int rc = 0;
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;
264 else if( control == IOBUFCTRL_DESC ) {
265 *(char**)buf = "decode_filter";
267 return rc;