e7e56408adb3c229373a10395e7d7e8fb641273f
[gnupg.git] / g10 / encr-data.c
1 /* encr-data.c -  process an encrypted data packet
2  *      Copyright (C) 1998 Free Software Foundation, Inc.
3  *
4  * This file is part of GNUPG.
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <assert.h>
26 #include "util.h"
27 #include "memory.h"
28 #include "packet.h"
29 #include "mpi.h"
30 #include "cipher.h"
31 #include "options.h"
32
33
34 static int decode_filter( void *opaque, int control, IOBUF a,
35                                         byte *buf, size_t *ret_len);
36
37 typedef struct {
38     CIPHER_HANDLE cipher_hd;
39 } decode_filter_ctx_t;
40
41
42
43 /****************
44  * Decrypt the data, specified by ED with the key DEK.
45  */
46 int
47 decrypt_data( PKT_encrypted *ed, DEK *dek )
48 {
49     decode_filter_ctx_t dfx;
50     byte *p;
51     int rc, c, i;
52     byte temp[16];
53
54     if( opt.verbose ) {
55         const char *s = cipher_algo_to_string( dek->algo );
56         if( s )
57             log_info("%s encrypted data\n", s );
58         else
59             log_info("encrypted with unknown algorithm %d\n", dek->algo );
60     }
61     if( (rc=check_cipher_algo(dek->algo)) )
62         return rc;
63     if( ed->len && ed->len < 10 )
64         log_bug("Nanu\n");   /* oops: found a bug */
65
66     dfx.cipher_hd = cipher_open( dek->algo, CIPHER_MODE_AUTO_CFB, 1 );
67     cipher_setkey( dfx.cipher_hd, dek->key, dek->keylen  );
68     cipher_setiv( dfx.cipher_hd, NULL );
69
70     if( ed->len ) {
71         iobuf_set_limit( ed->buf, ed->len );
72
73         for(i=0; i < 10 && ed->len; i++, ed->len-- )
74             temp[i] = iobuf_get(ed->buf);
75     }
76     else {
77         for(i=0; i < 10; i++ )
78             if( (c=iobuf_get(ed->buf)) == -1 )
79                 break;
80             else
81                 temp[i] = c;
82     }
83     cipher_decrypt( dfx.cipher_hd, temp, temp, 10);
84     cipher_sync( dfx.cipher_hd );
85     p = temp;
86     if( p[6] != p[8] || p[7] != p[9] ) {
87         cipher_close(dfx.cipher_hd);
88         return G10ERR_BAD_KEY;
89     }
90     iobuf_push_filter( ed->buf, decode_filter, &dfx );
91     proc_packets(ed->buf);
92     iobuf_pop_filter( ed->buf, decode_filter, &dfx );
93     if( ed->len )
94         iobuf_set_limit( ed->buf, 0 ); /* disable the readlimit */
95     else
96         iobuf_clear_eof( ed->buf );
97     ed->buf = NULL;
98     cipher_close(dfx.cipher_hd);
99     return 0;
100 }
101
102 static int
103 decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len)
104 {
105     decode_filter_ctx_t *fc = opaque;
106     size_t n, size = *ret_len;
107     int rc = 0;
108     int c;
109
110     if( control == IOBUFCTRL_UNDERFLOW ) {
111         assert(a);
112         for(n=0; n < size; n++ ) {
113             if( (c = iobuf_get(a)) == -1 )
114                 break;
115             buf[n] = c;
116         }
117
118         if( n )
119             cipher_decrypt( fc->cipher_hd, buf, buf, n);
120         else
121             rc = -1; /* eof */
122         *ret_len = n;
123     }
124     else if( control == IOBUFCTRL_DESC ) {
125         *(char**)buf = "decode_filter";
126     }
127     return rc;
128 }
129
130