* sign.c (gpgsm_sign): Print an error message on all failures.
[gnupg.git] / sm / decrypt.c
1 /* decrypt.c - Decrypt a message
2  *      Copyright (C) 2001, 2003 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 <errno.h>
26 #include <unistd.h> 
27 #include <time.h>
28 #include <assert.h>
29
30 #include "gpgsm.h"
31 #include <gcrypt.h>
32 #include <ksba.h>
33
34 #include "keydb.h"
35 #include "i18n.h"
36
37 struct decrypt_filter_parm_s {
38   int algo;
39   int mode;
40   int blklen;
41   gcry_cipher_hd_t hd;
42   char iv[16];
43   size_t ivlen;
44   int any_data;  /* dod we push anything through the filter at all? */
45   unsigned char lastblock[16];  /* to strip the padding we have to
46                                    keep this one */
47   char helpblock[16];  /* needed because there is no block buffering in
48                           libgcrypt (yet) */
49   int  helpblocklen;
50 };
51
52
53
54 /* Decrypt the session key and fill in the parm structure.  The
55    algo and the IV is expected to be already in PARM. */
56 static int 
57 prepare_decryption (const char *hexkeygrip, ksba_const_sexp_t enc_val,
58                     struct decrypt_filter_parm_s *parm)
59 {
60   char *seskey = NULL;
61   size_t n, seskeylen;
62   int rc;
63
64   rc = gpgsm_agent_pkdecrypt (hexkeygrip, enc_val,
65                               &seskey, &seskeylen);
66   if (rc)
67     {
68       log_error ("error decrypting session key: %s\n", gpg_strerror (rc));
69       goto leave;
70     }
71
72   if (DBG_CRYPTO)
73     log_printhex ("pkcs1 encoded session key:", seskey, seskeylen);
74
75   n=0;
76   if (seskeylen == 24)
77     {
78       /* Smells like a 3-des key.  This might happen because a SC has
79          already done the unpacking. fixme! */
80     }
81   else
82     {
83       if (n + 7 > seskeylen )
84         {
85           rc = gpg_error (GPG_ERR_INV_SESSION_KEY);
86           goto leave; 
87         }
88       
89       /* FIXME: Actually the leading zero is required but due to the way
90          we encode the output in libgcrypt as an MPI we are not able to
91          encode that leading zero.  However, when using a Smartcard we are
92          doing it the rightway and therefore we have to skip the zero.  This
93          should be fixed in gpg-agent of course. */
94       if (!seskey[n])
95         n++;
96       
97       if (seskey[n] != 2 )  /* wrong block type version */
98         { 
99           rc = gpg_error (GPG_ERR_INV_SESSION_KEY);
100           goto leave; 
101         }
102       
103       for (n++; n < seskeylen && seskey[n]; n++) /* skip the random bytes */
104         ;
105       n++; /* and the zero byte */
106       if (n >= seskeylen )
107         { 
108           rc = gpg_error (GPG_ERR_INV_SESSION_KEY);
109           goto leave; 
110         }
111     }
112
113   if (DBG_CRYPTO)
114     log_printhex ("session key:", seskey+n, seskeylen-n);
115
116   rc = gcry_cipher_open (&parm->hd, parm->algo, parm->mode, 0);
117   if (rc)
118     {
119       log_error ("error creating decryptor: %s\n", gpg_strerror (rc));
120       goto leave;
121     }
122                         
123   rc = gcry_cipher_setkey (parm->hd, seskey+n, seskeylen-n);
124   if (gpg_err_code (rc) == GPG_ERR_WEAK_KEY)
125     {
126       log_info (_("WARNING: message was encrypted with "
127                   "a weak key in the symmetric cipher.\n"));
128       rc = 0;
129     }
130   if (rc)
131     {
132       log_error("key setup failed: %s\n", gpg_strerror(rc) );
133       goto leave;
134     }
135
136   gcry_cipher_setiv (parm->hd, parm->iv, parm->ivlen);
137
138  leave:
139   xfree (seskey);
140   return rc;
141 }
142
143
144 /* This function is called by the KSBA writer just before the actual
145    write is done.  The function must take INLEN bytes from INBUF,
146    decrypt it and store it inoutbuf which has a maximum size of
147    maxoutlen.  The valid bytes in outbuf should be return in outlen.
148    Due to different buffer sizes or different length of input and
149    output, it may happen that fewer bytes are process or fewer bytes
150    are written. */
151 static gpg_error_t
152 decrypt_filter (void *arg,
153                 const void *inbuf, size_t inlen, size_t *inused,
154                 void *outbuf, size_t maxoutlen, size_t *outlen)
155 {
156   struct decrypt_filter_parm_s *parm = arg;
157   int blklen = parm->blklen;
158   size_t orig_inlen = inlen;
159
160   /* fixme: Should we issue an error when we have not seen one full block? */
161   if (!inlen)
162     return gpg_error (GPG_ERR_BUG);
163
164   if (maxoutlen < 2*parm->blklen)
165     return gpg_error (GPG_ERR_BUG);
166   /* make some space becuase we will later need an extra block at the end */
167   maxoutlen -= blklen;
168
169   if (parm->helpblocklen)
170     {
171       int i, j;
172
173       for (i=parm->helpblocklen,j=0; i < blklen && j < inlen; i++, j++)
174         parm->helpblock[i] = ((const char*)inbuf)[j];
175       inlen -= j;
176       if (blklen > maxoutlen)
177         return gpg_error (GPG_ERR_BUG);
178       if (i < blklen)
179         {
180           parm->helpblocklen = i;
181           *outlen = 0;
182         }
183       else
184         {
185           parm->helpblocklen = 0;
186           if (parm->any_data)
187             {
188               memcpy (outbuf, parm->lastblock, blklen);
189               *outlen =blklen;
190             }
191           else
192             *outlen = 0;
193           gcry_cipher_decrypt (parm->hd, parm->lastblock, blklen,
194                                parm->helpblock, blklen);
195           parm->any_data = 1;
196         }
197       *inused = orig_inlen - inlen;
198       return 0;
199     }
200
201
202   if (inlen > maxoutlen)
203     inlen = maxoutlen;
204   if (inlen % blklen)
205     { /* store the remainder away */
206       parm->helpblocklen = inlen%blklen;
207       inlen = inlen/blklen*blklen;
208       memcpy (parm->helpblock, (const char*)inbuf+inlen, parm->helpblocklen);
209     }
210
211   *inused = inlen + parm->helpblocklen;
212   if (inlen)
213     {
214       assert (inlen >= blklen);
215       if (parm->any_data)
216         {
217           gcry_cipher_decrypt (parm->hd, (char*)outbuf+blklen, inlen,
218                                inbuf, inlen);
219           memcpy (outbuf, parm->lastblock, blklen);
220           memcpy (parm->lastblock,(char*)outbuf+inlen, blklen);
221           *outlen = inlen;
222         }
223       else
224         {
225           gcry_cipher_decrypt (parm->hd, outbuf, inlen, inbuf, inlen);
226           memcpy (parm->lastblock, (char*)outbuf+inlen-blklen, blklen);
227           *outlen = inlen - blklen;
228           parm->any_data = 1;
229         }
230     }
231   else
232     *outlen = 0;
233   return 0;
234 }
235
236
237 \f
238 /* Perform a decrypt operation.  */
239 int
240 gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp)
241 {
242   int rc;
243   Base64Context b64reader = NULL;
244   Base64Context b64writer = NULL;
245   ksba_reader_t reader;
246   ksba_writer_t writer;
247   ksba_cms_t cms = NULL;
248   ksba_stop_reason_t stopreason;
249   KEYDB_HANDLE kh;
250   int recp;
251   FILE *in_fp = NULL;
252   struct decrypt_filter_parm_s dfparm;
253
254   memset (&dfparm, 0, sizeof dfparm);
255
256   kh = keydb_new (0);
257   if (!kh)
258     {
259       log_error (_("failed to allocated keyDB handle\n"));
260       rc = gpg_error (GPG_ERR_GENERAL);
261       goto leave;
262     }
263
264
265   in_fp = fdopen ( dup (in_fd), "rb");
266   if (!in_fp)
267     {
268       rc = gpg_error (gpg_err_code_from_errno (errno));
269       log_error ("fdopen() failed: %s\n", strerror (errno));
270       goto leave;
271     }
272
273   rc = gpgsm_create_reader (&b64reader, ctrl, in_fp, &reader);
274   if (rc)
275     {
276       log_error ("can't create reader: %s\n", gpg_strerror (rc));
277       goto leave;
278     }
279
280   rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer);
281   if (rc)
282     {
283       log_error ("can't create writer: %s\n", gpg_strerror (rc));
284       goto leave;
285     }
286
287   rc = ksba_cms_new (&cms);
288   if (rc)
289     goto leave;
290
291   rc = ksba_cms_set_reader_writer (cms, reader, writer);
292   if (rc)
293     {
294       log_debug ("ksba_cms_set_reader_writer failed: %s\n",
295                  gpg_strerror (rc));
296       goto leave;
297     }
298
299   /* parser loop */
300   do 
301     {
302       rc = ksba_cms_parse (cms, &stopreason);
303       if (rc)
304         {
305           log_debug ("ksba_cms_parse failed: %s\n", gpg_strerror (rc));
306           goto leave;
307         }
308
309       if (stopreason == KSBA_SR_BEGIN_DATA
310           || stopreason == KSBA_SR_DETACHED_DATA)
311         {
312           int algo, mode;
313           const char *algoid;
314           int any_key = 0;
315           
316           algoid = ksba_cms_get_content_oid (cms, 2/* encryption algo*/);
317           algo = gcry_cipher_map_name (algoid);
318           mode = gcry_cipher_mode_from_oid (algoid);
319           if (!algo || !mode)
320             {
321               rc = gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
322               log_error ("unsupported algorithm `%s'\n", algoid? algoid:"?");
323               if (algoid && !strcmp (algoid, "1.2.840.113549.3.2"))
324                 log_info (_("(this is the RC2 algorithm)\n"));
325               else if (!algoid)
326                 log_info (_("(this does not seem to be an encrypted"
327                             " message)\n"));
328               {
329                 char numbuf[50];
330                 sprintf (numbuf, "%d", rc);
331                 gpgsm_status2 (ctrl, STATUS_ERROR, "decrypt.algorithm",
332                                numbuf, algoid?algoid:"?", NULL);
333               }
334
335               goto leave;
336             }
337           dfparm.algo = algo;
338           dfparm.mode = mode;
339           dfparm.blklen = gcry_cipher_get_algo_blklen (algo);
340           if (dfparm.blklen > sizeof (dfparm.helpblock))
341             return gpg_error (GPG_ERR_BUG);
342
343           rc = ksba_cms_get_content_enc_iv (cms,
344                                             dfparm.iv,
345                                             sizeof (dfparm.iv),
346                                             &dfparm.ivlen);
347           if (rc)
348             {
349               log_error ("error getting IV: %s\n", gpg_strerror (rc));
350               goto leave;
351             }
352           
353           for (recp=0; !any_key; recp++)
354             {
355               char *issuer;
356               ksba_sexp_t serial;
357               ksba_sexp_t enc_val;
358               char *hexkeygrip = NULL;
359
360               rc = ksba_cms_get_issuer_serial (cms, recp, &issuer, &serial);
361               if (rc == -1 && recp)
362                 break; /* no more recipients */
363               if (rc)
364                 log_error ("recp %d - error getting info: %s\n",
365                            recp, gpg_strerror (rc));
366               else
367                 {
368                   ksba_cert_t cert = NULL;
369
370                   log_debug ("recp %d - issuer: `%s'\n",
371                              recp, issuer? issuer:"[NONE]");
372                   log_debug ("recp %d - serial: ", recp);
373                   gpgsm_dump_serial (serial);
374                   log_printf ("\n");
375
376                   keydb_search_reset (kh);
377                   rc = keydb_search_issuer_sn (kh, issuer, serial);
378                   if (rc)
379                     {
380                       log_error ("failed to find the certificate: %s\n",
381                                  gpg_strerror(rc));
382                       goto oops;
383                     }
384
385                   rc = keydb_get_cert (kh, &cert);
386                   if (rc)
387                     {
388                       log_error ("failed to get cert: %s\n", gpg_strerror (rc));
389                       goto oops;     
390                     }
391                   /* Just in case there is a problem with the own
392                      certificate we print this message - should never
393                      happen of course */
394                   rc = gpgsm_cert_use_decrypt_p (cert);
395                   if (rc)
396                     {
397                       char numbuf[50];
398                       sprintf (numbuf, "%d", rc);
399                       gpgsm_status2 (ctrl, STATUS_ERROR, "decrypt.keyusage",
400                                      numbuf, NULL);
401                       rc = 0;
402                     }
403
404                   hexkeygrip = gpgsm_get_keygrip_hexstring (cert);
405
406                 oops:
407                   xfree (issuer);
408                   xfree (serial);
409                   ksba_cert_release (cert);
410                 }
411
412               if (!hexkeygrip)
413                 ;
414               else if (!(enc_val = ksba_cms_get_enc_val (cms, recp)))
415                 log_error ("recp %d - error getting encrypted session key\n",
416                            recp);
417               else
418                 {
419                   rc = prepare_decryption (hexkeygrip, enc_val, &dfparm);
420                   xfree (enc_val);
421                   if (rc)
422                     {
423                       log_debug ("decrypting session key failed: %s\n",
424                                  gpg_strerror (rc));
425                     }
426                   else
427                     { /* setup the bulk decrypter */
428                       any_key = 1;
429                       ksba_writer_set_filter (writer,
430                                               decrypt_filter,
431                                               &dfparm);
432                     }
433                 }
434             }
435           if (!any_key)
436             {
437               rc = gpg_error (GPG_ERR_NO_SECKEY);
438               goto leave;
439             }
440         }
441       else if (stopreason == KSBA_SR_END_DATA)
442         {
443           ksba_writer_set_filter (writer, NULL, NULL);
444           if (dfparm.any_data)
445             { /* write the last block with padding removed */
446               int i, npadding = dfparm.lastblock[dfparm.blklen-1];
447               if (!npadding || npadding > dfparm.blklen)
448                 {
449                   log_error ("invalid padding with value %d\n", npadding);
450                   rc = gpg_error (GPG_ERR_INV_DATA);
451                   goto leave;
452                 }
453               rc = ksba_writer_write (writer,
454                                       dfparm.lastblock, 
455                                       dfparm.blklen - npadding);
456               if (rc)
457                   goto leave;
458
459               for (i=dfparm.blklen - npadding; i < dfparm.blklen; i++)
460                 {
461                   if (dfparm.lastblock[i] != npadding)
462                     {
463                       log_error ("inconsistent padding\n");
464                       rc = gpg_error (GPG_ERR_INV_DATA);
465                       goto leave;
466                     }
467                 }
468             }
469         }
470
471     }
472   while (stopreason != KSBA_SR_READY);   
473
474   rc = gpgsm_finish_writer (b64writer);
475   if (rc) 
476     {
477       log_error ("write failed: %s\n", gpg_strerror (rc));
478       goto leave;
479     }
480   gpgsm_status (ctrl, STATUS_DECRYPTION_OKAY, NULL);
481
482
483  leave:
484   if (rc)
485     {
486       gpgsm_status (ctrl, STATUS_DECRYPTION_FAILED, NULL);
487       log_error ("message decryption failed: %s\n", gpg_strerror (rc));
488     }
489   ksba_cms_release (cms);
490   gpgsm_destroy_reader (b64reader);
491   gpgsm_destroy_writer (b64writer);
492   keydb_release (kh); 
493   if (in_fp)
494     fclose (in_fp);
495   if (dfparm.hd)
496     gcry_cipher_close (dfparm.hd); 
497   return rc;
498 }
499
500